home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-12-19 | 81.7 KB | 3,769 lines |
- Newsgroups: comp.sources.unix
- From: jnweiger@immd4.informatik.uni-erlangen.de (Juergen Weigert)
- Subject: v25i048: Screen3 - multiple windows on an ASCII terminal, Part08/08
- Sender: sources-moderator@pa.dec.com
- Approved: vixie@pa.dec.com
-
- Submitted-By: jnweiger@immd4.informatik.uni-erlangen.de (Juergen Weigert)
- Posting-Number: Volume 25, Issue 48
- Archive-Name: screen3/part08
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 8 (of 8)."
- # Contents: screen.c
- # Wrapped by vixie@cognition.pa.dec.com on Thu Dec 19 17:36:06 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'screen.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'screen.c'\"
- else
- echo shar: Extracting \"'screen.c'\" \(78493 characters\)
- sed "s/^X//" >'screen.c' <<'END_OF_FILE'
- X/* Copyright (c) 1991
- X * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
- X * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
- X * Copyright (c) 1987 Oliver Laumann
- X *
- X * This program is free software; you can redistribute it and/or modify
- X * it under the terms of the GNU General Public License as published by
- X * the Free Software Foundation; either version 1, or (at your option)
- X * any later version.
- X *
- X * This program is distributed in the hope that it will be useful,
- X * but WITHOUT ANY WARRANTY; without even the implied warranty of
- X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- X * GNU General Public License for more details.
- X *
- X * You should have received a copy of the GNU General Public License
- X * along with this program (see the file COPYING); if not, write to the
- X * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- X *
- X * Noteworthy contributors to screen's design and implementation:
- X * Wayne Davison (davison@borland.com)
- X * Patrick Wolfe (pat@kai.com, kailand!pat)
- X * Bart Schaefer (schaefer@cse.ogi.edu)
- X * Nathan Glasser (nathan@brokaw.lcs.mit.edu)
- X * Larry W. Virden (lwv27%cas.BITNET@CUNYVM.CUNY.Edu)
- X * Howard Chu (hyc@hanauma.jpl.nasa.gov)
- X * Tim MacKenzie (tym@dibbler.cs.monash.edu.au)
- X * Markku Jarvinen (mta@{cc,cs,ee}.tut.fi)
- X * Marc Boucher (marc@CAM.ORG)
- X *
- X ****************************************************************
- X */
- X
- X#ifndef lint
- X static char rcs_id[] = "$Id: screen.c,v 1.106 91/10/11 11:24:50 jnweiger Exp $ FAU";
- X#endif
- X
- X
- X#if defined(BSD) || defined(sequent) || defined(pyr)
- X# include <strings.h>
- X#else
- X# include <string.h>
- X#endif
- X#include <sys/param.h>
- X#include <signal.h>
- X#include <ctype.h>
- X#include <pwd.h>
- X#include <fcntl.h>
- X#if defined(SGI)
- X#include <sys/sysmacros.h>
- X/* #include <sys/utsname.h> we define SYSV anyway, right? */
- X#endif
- X#if !defined(sun) && !defined(B43)
- X# include <time.h>
- X#endif
- X#if defined(sun) || defined(_IBMR2) || defined(sysV68) || defined(MIPS) || defined(GOULD_NP1) || defined(B43)
- X# include <sys/time.h>
- X#endif
- X#ifdef M_XENIX
- X#include <sys/select.h> /* for timeval */
- X#endif
- X#include <sys/types.h>
- X#if !defined(sysV68) && !defined(M_XENIX)
- X# include <sys/wait.h>
- X#endif
- X#include <sys/stat.h>
- X#include <sys/file.h>
- X#ifndef sun
- X# include <sys/ioctl.h>
- X#endif /* sun */
- X
- X#include "config.h"
- X
- X#ifdef SVR4
- X#include <sys/stropts.h>
- X#endif
- X#ifdef SYSV
- X#include <sys/utsname.h>
- X#endif
- X
- X#if defined(_SEQUENT_) || defined(M_XENIX)
- X/* for the FD.. stuff */
- X# include <sys/select.h>
- X#endif
- X#ifdef sequent
- X# include <sys/resource.h>
- X#endif /* sequent */
- X
- X#include "screen.h"
- X#include "patchlevel.h"
- X
- X#if defined(xelos) || defined(sysV68) || defined(M_XENIX)
- X struct passwd *getpwuid __P((uid_t));
- X struct passwd *getpwnam __P((char *));
- X#endif
- X
- X#ifdef USEVARARGS
- X# if defined(__STDC__)
- X# include <stdarg.h>
- X# else
- X# include <varargs.h>
- X# endif
- X#endif
- X
- X#ifdef DEBUG
- XFILE *dfp;
- X#endif
- X
- X
- X#ifdef COPY_PASTE
- extern char *copybuffer; /* def in mark.c jw. */
- extern copylen;
- X#endif /* COPY_PASTE */
- X
- extern char *blank, *null, Term[], screenterm[], **environ, *Termcap;
- int force_vt = 1, assume_LP = 0;
- extern int in_ovl;
- extern int ovl_blockfore;
- extern void (*ovl_process)();
- extern int help_page;
- extern int screenwidth, screenheight;
- extern int default_width, default_height;
- extern int Z0width, Z1width;
- extern int ISO2022;
- extern int status, HS;
- extern char *Z0, *WS, *LastMsg;
- extern time_t TimeDisplayed;
- int BellDisplayed;
- int VBellWait, MsgWait, MsgMinWait;
- X
- X/* tputs uses that: jw */
- extern short ospeed;
- X
- extern flowctl, wrap, visual_bell, default_monitor;
- extern int errno;
- extern sys_nerr;
- extern char *sys_errlist[];
- extern char mark_key_tab[];
- X
- X#ifdef TIOCGWINSZ
- extern struct winsize glwz;
- X#endif
- X
- static char *MakeWinMsg __P((char *, int));
- static void MakeNewEnv __P((void));
- static int Attach __P((int));
- static void Attacher __P((void));
- static void SigHandler __P((void));
- static sig_t SigChld __P(SIGPROTOARG);
- static sig_t SigInt __P(SIGPROTOARG);
- static sig_t CoreDump __P((int));
- static void DoWait __P((void));
- static sig_t Finit __P((int));
- static void InitKeytab __P((void));
- static void SetForeWindow __P((int));
- static int NextWindow __P((void));
- static int PreviousWindow __P((void));
- static int MoreWindows __P((void));
- static void FreeWindow __P((struct win *));
- static void execvpe __P((char *, char **, char **));
- static void LogToggle __P((void));
- static void ShowWindows __P((void));
- static void ShowTime __P((void));
- static void ShowInfo __P((void));
- static int OpenPTY __P((void));
- static void trysend __P((int, struct msg *, char *));
- X#if defined(SIGWINCH) && defined(TIOCGWINSZ)
- static sig_t SigAttWinch __P(SIGPROTOARG);
- X#endif
- static void fgtty __P((void));
- static void freetty __P((void));
- X#ifdef BSDJOBS
- static void brktty __P((void));
- X#endif
- X
- X#if defined(LOCK)
- static sig_t DoLock __P(SIGPROTOARG);
- static void LockTerminal __P((void));
- X#endif
- X
- X#ifdef COPY_PASTE
- static pastelen;
- static char *pastebuffer;
- X#endif
- X#ifdef PASSWORD
- extern char Password[];
- X#endif
- X
- static struct passwd *ppp;
- static char PtyName[32], TtyName[32];
- char *ShellProg;
- char *ShellArgs[2];
- static char inbuf[MAXWIN][IOSIZE];
- static inlen[MAXWIN];
- static inbuf_ct;
- static ESCseen;
- static GotSignal;
- X
- static char DefaultShell[] = "/bin/sh";
- static char DefaultPath[] = ":/usr/ucb:/bin:/usr/bin";
- X#if !(defined(sequent) || defined(_SEQUENT_) || defined(SVR4))
- static char PtyProto[] = "/dev/ptyXY";
- static char TtyProto[] = "/dev/ttyXY";
- X#endif
- int TtyMode = 0622;
- X#ifdef SOCKDIR
- char *SockDir = SOCKDIR;
- X#else
- char *SockDir = ".screen";
- X#endif
- extern char SockPath[], *SockNamePtr, *SockName;
- int ServerSocket = -1;
- static char **NewEnv;
- X
- char *RcFileName = NULL;
- char Esc = Ctrl('a');
- char MetaEsc = 'a';
- char *home;
- X
- int HasWindow;
- char *LoginName;
- char *BellString;
- char *VisualBellString;
- char *ActivityString;
- char *PowDetachString;
- int auto_detach = 1;
- int iflag, mflag, rflag, dflag, lsflag, quietflag, wipeflag;
- int adaptflag, loginflag = -1;
- static intrc, startc, stopc;
- char HostName[MAXSTR];
- int Detached, Suspended;
- int DeadlyMsg = 1;
- int AttacherPid; /* Non-Zero in child if we have an attacher */
- int real_uid, real_gid, eff_uid, eff_gid;
- int default_histheight;
- int default_startup;
- int slowpaste;
- X
- X#if !defined(POSIX) && defined(BSDJOBS)
- int DevTty = -1;
- X#endif
- X
- X#ifdef NETHACK
- int nethackflag = 0;
- X#endif
- X
- struct mode OldMode, NewMode;
- X
- struct win *fore = NULL;
- int WinList = -1;
- int ForeNum;
- struct win *wtab[MAXWIN];
- X
- struct key ktab[256];
- X
- X#ifndef FD_SET
- typedef struct fd_set
- X{
- X int fd_bits[1];
- X} fd_set;
- X# define FD_ZERO(fd) ((fd)->fd_bits[0] = 0)
- X# define FD_SET(b,fd) ((fd)->fd_bits[0] |= 1 << (b))
- X# define FD_ISSET(b,fd) ((fd)->fd_bits[0] & 1 << (b))
- X# define FD_SETSIZE 32
- X#endif
- X
- X
- X#ifndef WTERMSIG
- X# ifndef BSDWAIT /* if wait is NOT a union: */
- X# define WTERMSIG(status) (status & 0177)
- X# else
- X# define WTERMSIG(status) status.w_T.w_Termsig
- X# endif
- X#endif
- X
- X#ifndef WIFCORESIG
- X# ifndef BSDWAIT /* if wait is NOT a union: */
- X# define WIFCORESIG(status) (status & 0200)
- X# else
- X# define WIFCORESIG(status) status.w_T.w_Coredump
- X# endif
- X#endif
- X
- X#ifndef WEXITSTATUS
- X# ifndef BSDWAIT /* if wait is NOT a union: */
- X# define WEXITSTATUS(status) ((status >> 8) & 0377)
- X# else
- X# define WEXITSTATUS(status) status.w_T.w_Retcode
- X# endif
- X#endif
- X
- char *shellaka = NULL;
- X
- X/*
- X * Do this last
- X */
- X#include "extern.h"
- X
- X/*
- X * XXX: Missing system header files.
- X */
- X#ifdef USEVARARGS
- X#ifdef SVR4
- int vsprintf __P((char *, const char *, va_list));
- X#else
- int vsprintf __P((char *, char *, va_list));
- X#endif
- X#endif
- int select __P((int, fd_set *, fd_set *, fd_set *, struct timeval *));
- X
- X#ifdef BSDJOBS
- static void
- brktty()
- X{
- X# ifdef POSIX
- X setsid(); /* will break terminal affilition */
- X# else
- X if (DevTty)
- X if (ioctl(DevTty, TIOCNOTTY, (char *) 0) != 0)
- X debug2("brktty: ioctl(DevTty=%d, TIOCNOTTY, 0) = %d\n", DevTty, errno);
- X# endif
- X}
- X#endif
- X
- static void
- freetty()
- X{
- X#ifdef BSDJOBS
- X brktty();
- X# ifndef POSIX
- X if (DevTty >= 0)
- X {
- X close(DevTty);
- X DevTty = -1;
- X }
- X# endif
- X#endif
- X close(0);
- X close(1);
- X close(2);
- X}
- X
- static void
- fgtty()
- X{
- X#ifdef BSDJOBS
- X int mypid;
- X
- X mypid = getpid();
- X# ifdef POSIX
- X if (tcsetpgrp(0, mypid))
- X# else
- X if (ioctl(0, TIOCSPGRP, &mypid) != 0)
- X# endif
- X debug1("fgtty: tcsetpgrp: %d\n", errno);
- X# ifdef POSIX
- X# ifdef SVR4
- X if (getpgid(0) != mypid)
- X# endif
- X if (setpgid(0, mypid))
- X# else
- X if (setpgrp(0, mypid))
- X# endif
- X debug1("fgtty: setpgid: %d\n", errno);
- X#endif
- X}
- X
- X#ifdef hpux
- X/*
- X * hpux has berkeley signal semantics if we use sigvector,
- X * but not, if we use signal, so we define our own signal() routine.
- X * (jw)
- X */
- void (*signal(sig, func)) ()
- int sig;
- void (*func) ();
- X{
- X struct sigvec osv, sv;
- X
- X sv.sv_handler = func;
- X sv.sv_mask = sigmask(sig);
- X sv.sv_flags = SV_BSDSIG;
- X if (sigvector(sig, &sv, &osv) < 0)
- X return (BADSIG);
- X return (osv.sv_handler);
- X}
- X#endif /* hpux */
- X
- X#ifndef USEBCOPY
- void bcopy(s1, s2, len)
- register char *s1, *s2;
- register int len;
- X{
- X if (s1 < s2 && s2 < s1 + len)
- X {
- X s1 += len;
- X s2 += len;
- X while (len-- > 0)
- X *--s2 = *--s1;
- X }
- X else
- X while (len-- > 0)
- X *s2++ = *s1++;
- X}
- X#endif /* USEBCOPY */
- X
- void bclear(p, n)
- int n;
- char *p;
- X{
- X bcopy(blank, p, n);
- X}
- X
- void main(ac, av)
- int ac;
- char **av;
- X{
- X register int n, len;
- X register struct win *p;
- X char *ap, *aka = NULL;
- X char *av0;
- X int s = 0;
- X fd_set r, w;
- X int aflag = 0;
- X struct timeval tv;
- X int nsel;
- X char buf[IOSIZE], *bufp, *myname = (ac == 0) ? "screen" : av[0];
- X struct stat st;
- X int buflen, tmp;
- X#ifdef _MODE_T /* (jw) */
- X mode_t oumask;
- X#else
- X int oumask;
- X#endif
- X#ifdef SYSV
- X struct utsname utsnam;
- X#endif
- X
- X/*
- X * First, close all unused descriptors
- X * (otherwise, we might have problems with the select() call)
- X */
- X#ifdef SYSV
- X for (n = NOFILE - 1; n > 2; n--)
- X close(n);
- X#else
- X for (n = getdtablesize() - 1; n > 2; n--)
- X close(n);
- X#endif
- X#ifdef DEBUG
- X (void) mkdir("/tmp/debug", 0777);
- X if ((dfp = fopen("/tmp/debug/screen.front", "w")) == NULL)
- X dfp = stderr;
- X else
- X (void) chmod("/tmp/debug/screen.front", 0666);
- X#endif
- X debug1("-- screen debug started %s\n", *av);
- X#ifdef POSIX
- X debug("POSIX\n");
- X#endif
- X#ifdef TERMIO
- X debug("TERMIO\n");
- X#endif
- X#ifdef SYSV
- X debug("SYSV\n");
- X#endif
- X#ifdef NAMEDPIPE
- X debug("NAMEDPIPE\n");
- X#endif
- X#if defined(SIGWINCH) && defined(TIOCGWINSZ)
- X debug("Window changing enabled\n");
- X#endif
- X#ifdef NOREUID
- X debug("NOREUID\n");
- X#endif
- X#ifdef hpux
- X debug("hpux\n");
- X#endif
- X#ifdef USEBCOPY
- X debug("USEBCOPY\n");
- X#endif
- X#ifdef UTMPOK
- X debug("UTMPOK\n");
- X#endif
- X#ifdef LOADAV
- X debug("LOADAV\n");
- X#endif
- X#ifdef NETHACK
- X debug("NETHACK\n");
- X#endif
- X#ifdef TERMINFO
- X debug("TERMINFO\n");
- X#endif
- X
- X BellString = SaveStr("Bell in window %");
- X VisualBellString = SaveStr(" Wuff, Wuff!! ");
- X ActivityString = SaveStr("Activity in window %");
- X PowDetachString = 0;
- X default_histheight = DEFAULTHISTHEIGHT;
- X default_startup = (ac > 1) ? 0 : 1;
- X adaptflag = 0;
- X slowpaste = 0;
- X VBellWait = VBELLWAIT;
- X MsgWait = MSGWAIT;
- X MsgMinWait = MSGMINWAIT;
- X CompileKeys(NULL, mark_key_tab);
- X
- X av0 = *av;
- X while (ac > 0)
- X {
- X ap = *++av;
- X if (--ac > 0 && *ap == '-')
- X {
- X switch (ap[1])
- X {
- X case 'a':
- X aflag = 1;
- X break;
- X case 'A':
- X adaptflag = 1;
- X break;
- X case 'c':
- X if (ap[2])
- X RcFileName = ap + 2;
- X else
- X {
- X if (--ac == 0)
- X exit_with_usage(myname);
- X RcFileName = *++av;
- X }
- X break;
- X case 'e':
- X if (ap[2])
- X ap += 2;
- X else
- X {
- X if (--ac == 0)
- X exit_with_usage(myname);
- X ap = *++av;
- X }
- X if (!ParseEscape(ap))
- X Msg(0, "Two characters are required with -e option.");
- X break;
- X case 'f':
- X switch (ap[2])
- X {
- X case 'n':
- X case '0':
- X flowctl = 1;
- X break;
- X case 'y':
- X case '1':
- X case '\0':
- X flowctl = 2;
- X break;
- X case 'a':
- X flowctl = 3;
- X break;
- X default:
- X exit_with_usage(myname);
- X }
- X break;
- X case 'h':
- X if (ap[2])
- X default_histheight = atoi(ap + 2);
- X else
- X {
- X if (--ac == 0)
- X exit_with_usage(myname);
- X default_histheight = atoi(*++av);
- X }
- X if (default_histheight < 0)
- X default_histheight = 0;
- X break;
- X case 'i':
- X iflag = 1;
- X break;
- X case 't': /* title is a synonym for AkA */
- X case 'k':
- X if (ap[2])
- X aka = ap + 2;
- X else
- X {
- X if (--ac == 0)
- X exit_with_usage(myname);
- X aka = *++av;
- X }
- X break;
- X case 'l':
- X switch (ap[2])
- X {
- X case 'n':
- X case '0':
- X loginflag = 0;
- X break;
- X case 'y':
- X case '1':
- X case '\0':
- X loginflag = 1;
- X break;
- X case 's':
- X case 'i':
- X lsflag = 1;
- X break;
- X default:
- X exit_with_usage(myname);
- X }
- X break;
- X case 'w':
- X lsflag = 1;
- X wipeflag = 1;
- X break;
- X case 'L':
- X assume_LP = 1;
- X break;
- X case 'm':
- X mflag = 1;
- X break;
- X case 'O':
- X force_vt = 0;
- X break;
- X case 'T':
- X if (ap[2])
- X {
- X if ((unsigned)strlen(ap+2) < 20)
- X strcpy(screenterm, ap + 2);
- X }
- X else
- X {
- X if (--ac == 0)
- X exit_with_usage(myname);
- X if ((unsigned)strlen(*++av) < 20)
- X strcpy(screenterm, *av);
- X }
- X break;
- X case 'q':
- X quietflag = 1;
- X break;
- X case 'r':
- X if (ap[2])
- X {
- X SockName = ap + 2;
- X if (ac != 1)
- X exit_with_usage(myname);
- X }
- X else if (--ac == 1)
- X {
- X if (*av[1] != '-')
- X SockName = *++av;
- X }
- X else if (ac != 0)
- X exit_with_usage(myname);
- X rflag = 1;
- X break;
- X case 'R':
- X rflag = 2;
- X break;
- X#ifdef REMOTE_DETACH
- X case 'd':
- X dflag = 1;
- X /* FALLTHRU */
- X case 'D':
- X if (!dflag)
- X dflag = 2;
- X if (ap[2])
- X SockName = ap + 2;
- X if (ac == 2)
- X {
- X if (*av[1] != '-')
- X {
- X SockName = *++av;
- X ac--;
- X }
- X }
- X break;
- X#endif
- X case 's':
- X if (ap[2])
- X ShellProg = ap + 2;
- X else
- X {
- X if (--ac == 0)
- X exit_with_usage(myname);
- X ShellProg = *++av;
- X }
- X break;
- X default:
- X exit_with_usage(myname);
- X }
- X }
- X else
- X break;
- X }
- X real_uid = getuid();
- X real_gid = getgid();
- X eff_uid = geteuid();
- X eff_gid = getegid();
- X if (!ShellProg && (ShellProg = getenv("SHELL")) == 0)
- X ShellProg = DefaultShell;
- X ShellArgs[0] = ShellProg;
- X#ifdef NETHACK
- X nethackflag = (getenv("NETHACKOPTIONS") != NULL);
- X#endif
- X home = getenv("HOME"); /* may or may not return a result. jw. */
- X if ((LoginName = getlogin()) == 0 || LoginName[0] == '\0')
- X {
- X if ((ppp = getpwuid(real_uid)) == 0)
- X {
- X#ifdef NETHACK
- X if (nethackflag)
- X Msg(0, "An alarm sounds through the dungeon...\nWarning, the kops are coming.");
- X else
- X#endif
- X Msg(0, "getpwuid() can't identify your account!");
- X exit(1);
- X }
- X LoginName = ppp->pw_name;
- X }
- X /* is anyone cheating? jw. */
- X if (((ppp != (struct passwd *) 0) && (LoginName == ppp->pw_name)) ||
- X ((ppp = getpwnam(LoginName)) != (struct passwd *) 0))
- X {
- X if (ppp->pw_uid != real_uid)
- X {
- X#ifdef NETHACK
- X if (nethackflag)
- X Msg(0, "You cannot resist to mimic a pile of gold.\nThe system ignores you.");
- X else
- X#endif
- X Msg(0, "getuid() and pw_uid don't match!");
- X exit(1);
- X }
- X }
- X else
- X {
- X#ifdef NETHACK
- X if (nethackflag)
- X Msg(0, "An alarm sounds through the dungeon...\nWarning, the kops are after you.");
- X else
- X#endif
- X Msg(0, "getpwnam() can't identify your account!");
- X exit(1);
- X }
- X if (home == 0 || *home == '\0')
- X home = ppp->pw_dir;
- X if ((unsigned)strlen(LoginName) > 20)
- X Msg(0, "LoginName too long - sorry.");
- X if ((unsigned)strlen(home) > MAXPATH - 25)
- X Msg(0, "$HOME too long - sorry.");
- X#ifdef PASSWORD
- X strcpy(Password, ppp->pw_passwd);
- X#endif
- X
- X if (!isatty(0))
- X {
- X#ifdef NETHACK
- X if (nethackflag)
- X Msg(0, "You must play from a terminal.");
- X else
- X#endif
- X Msg(0, "Must be connected to a terminal.");
- X exit(1);
- X }
- X#ifdef _MODE_T
- X oumask = umask(0); /* well, unsigned never fails? jw. */
- X#else
- X if ((oumask = umask(0)) == -1)
- X Msg(errno, "Cannot change umask to zero");
- X#endif
- X if ((SockDir = getenv("ISCREENDIR")) == NULL)
- X SockDir = getenv("SCREENDIR");
- X if (SockDir && (unsigned)strlen(SockDir) >= MAXPATH - 1)
- X Msg(0, "ridiculous long $(I)SCREENDIR - try again.");
- X#ifndef SOCKDIR
- X if (SockDir == 0)
- X {
- X sprintf(SockPath, "%s/.screen", home);
- X SockDir = SockPath;
- X }
- X#endif
- X if (SockDir)
- X {
- X if (access(SockDir, F_OK))
- X {
- X if (UserContext() > 0)
- X {
- X if (mkdir(SockDir, 0700))
- X UserReturn(0);
- X UserReturn(1);
- X }
- X if (UserStatus() <= 0)
- X Msg(0, "Cannot make directory '%s'", SockDir);
- X }
- X if (SockDir != SockPath)
- X strcpy(SockPath, SockDir);
- X }
- X#ifdef SOCKDIR
- X else
- X {
- X SockDir = SOCKDIR;
- X if (stat(SockDir, &st))
- X {
- X if (mkdir(SockDir, eff_uid ? 0777 : 0755) == -1)
- X Msg(errno, "Cannot make directory '%s'", SockDir);
- X }
- X else
- X {
- X n = eff_uid ? 0777 : 0755;
- X if ((st.st_mode & 0777) != n)
- X Msg(0, "Directory '%s' must have mode %03o.", SockDir, n);
- X }
- X sprintf(SockPath, "%s/S-%s", SockDir, LoginName);
- X if (access(SockPath, F_OK))
- X {
- X if (mkdir(SockPath, 0700) == -1)
- X Msg(errno, "Cannot make directory '%s'", SockPath);
- X (void) chown(SockPath, real_uid, real_gid);
- X }
- X }
- X#endif
- X if (stat(SockPath, &st) == -1)
- X {
- X Msg(errno, "Cannot access %s", SockPath);
- X }
- X else
- X {
- X if ((st.st_mode & S_IFMT) != S_IFDIR)
- X Msg(0, "%s is not a directory.", SockPath);
- X if (st.st_uid != real_uid)
- X Msg(0, "You are not the owner of %s.", SockPath);
- X if ((st.st_mode & 0777) != 0700)
- X Msg(0, "Directory %s must have mode 700.", SockPath);
- X }
- X strcat(SockPath, "/");
- X SockNamePtr = SockPath + strlen(SockPath);
- X (void) umask(oumask);
- X#ifdef SYSV
- X if (uname(&utsnam) == -1)
- X Msg(0, "uname() failed, errno = %d", errno);
- X else
- X {
- X strncpy(HostName, utsnam.nodename, MAXSTR);
- X HostName[(sizeof(utsnam.nodename) <= MAXSTR) ?
- X sizeof(utsnam.nodename) : MAXSTR] = '\0';
- X }
- X#else
- X (void) gethostname(HostName, MAXSTR);
- X#endif
- X HostName[MAXSTR - 1] = '\0';
- X if ((ap = index(HostName, '.')) != NULL)
- X *ap = '\0';
- X GetTTY(0, &OldMode);
- X#ifdef POSIX
- X ospeed = (short) cfgetospeed(&OldMode.tio);
- X#else
- X# ifndef TERMIO
- X ospeed = (short) OldMode.m_ttyb.sg_ospeed;
- X# endif
- X#endif
- X debug1("...setting extern short ospeed = %d\n", ospeed);
- X
- X if (lsflag)
- X {
- X int i;
- X i = FindSocket(0, NULL);
- X /* MakeClientSocket appended the last SockName there: */
- X *SockNamePtr = '\0';
- X if (i == 0)
- X {
- X#ifdef NETHACK
- X if (nethackflag)
- X Msg(0, "This room is empty (%s)\n", SockPath);
- X else
- X#endif /* NETHACK */
- X Msg(0, "No Sockets found in %s\n", SockPath);
- X }
- X else
- X Msg(0, "%d Socket%s in %s.\n", i, i > 1 ? "s" : "", SockPath);
- X /* NOTREACHED */
- X }
- X if (rflag)
- X {
- X debug("screen -r: - is there anybody out there?\n");
- X if (Attach(MSG_ATTACH))
- X {
- X Attacher();
- X /* NOTREACHED */
- X }
- X debug("screen -r: backend not responding -- still crying\n");
- X }
- X else if (dflag)
- X {
- X (void) Attach(MSG_DETACH);
- X DeadlyMsg = 0;
- X Msg(0, "[%s %sdetached.]\n", SockName, (dflag > 1 ? "power " : ""));
- X eexit(0);
- X /* NOTREACHED */
- X }
- X if (GetSockName())
- X {
- X s = MakeClientSocket(1, SockName);
- X if (ac == 0)
- X {
- X ac = 1;
- X av = ShellArgs;
- X }
- X av[ac] = aka;
- X SendCreateMsg(s, ac, av, aflag, flowctl, loginflag, default_histheight,
- X screenterm);
- X close(s);
- X exit(0);
- X }
- X#if !defined(POSIX) && defined(BSDJOBS)
- X if ((DevTty = open("/dev/tty", O_RDWR | O_NDELAY)) == -1)
- X Msg(errno, "/dev/tty");
- X#endif
- X switch (fork())
- X {
- X case -1:
- X Msg(errno, "fork");
- X /* NOTREACHED */
- X case 0:
- X break;
- X default:
- X Attacher();
- X /* NOTREACHED */
- X }
- X#ifdef DEBUG
- X if (dfp != stderr)
- X fclose(dfp);
- X if ((dfp = fopen("/tmp/debug/screen.back", "w")) == NULL)
- X dfp = stderr;
- X else
- X (void) chmod("/tmp/debug/screen.back", 0666);
- X#endif
- X debug("-- screen.back debug started\n");
- X ap = av0 + strlen(av0) - 1;
- X while (ap >= av0)
- X {
- X if (!strncmp("screen", ap, 6))
- X {
- X strncpy(ap, "SCREEN", 6); /* name this process "SCREEN-BACKEND" */
- X break;
- X }
- X ap--;
- X }
- X if (ap < av0)
- X *av0 = 'S';
- X
- X AttacherPid = getppid();
- X ServerSocket = s = MakeServerSocket();
- X#ifdef ETCSCREENRC
- X if ((ap = getenv("SYSSCREENRC")) == NULL)
- X StartRc(ETCSCREENRC);
- X else
- X StartRc(ap);
- X#endif
- X StartRc(RcFileName);
- X InitTermcap();
- X InitTerm(0);
- X MakeNewEnv();
- X#ifdef UTMPOK
- X InitUtmp();
- X#endif
- X#ifdef LOADAV
- X InitKmem();
- X#endif
- X signal(SIGHUP, SigHup);
- X signal(SIGINT, Finit);
- X signal(SIGQUIT, Finit);
- X signal(SIGTERM, Finit);
- X#ifdef BSDJOBS
- X signal(SIGTTIN, SIG_IGN);
- X signal(SIGTTOU, SIG_IGN);
- X#endif
- X if (eff_uid != real_uid)
- X {
- X /* if running with s-bit, we must install a special signal
- X * handler routine that resets the s-bit, so that we get a
- X * core file anyway.
- X */
- X signal(SIGBUS, CoreDump);
- X signal(SIGSEGV, CoreDump);
- X }
- X InitKeytab();
- X#ifdef ETCSCREENRC
- X if ((ap = getenv("SYSSCREENRC")) == NULL)
- X FinishRc(ETCSCREENRC);
- X else
- X FinishRc(ap);
- X#endif
- X FinishRc(RcFileName);
- X SetMode(&OldMode, &NewMode);
- X SetTTY(0, &NewMode);
- X if (loginflag == -1)
- X loginflag = LOGINDEFAULT;
- X if (ac == 0)
- X {
- X ac = 1;
- X av = ShellArgs;
- X if (!aka)
- X aka = shellaka;
- X }
- X if (!HasWindow)
- X {
- X debug("We open one default window, as screenrc did not specify one.\n");
- X if (MakeWindow(aka, av, aflag, flowctl, 0, (char *) 0, loginflag, -1, 0) == -1)
- X {
- X Finit(1);
- X /* NOTREACHED */
- X }
- X }
- X if (default_startup)
- X display_copyright();
- X#ifdef SYSV
- X signal(SIGCLD, SigChld);
- X#else
- X signal(SIGCHLD, SigChld);
- X#endif
- X signal(SIGINT, SigInt);
- X tv.tv_usec = 0;
- X if (rflag == 2)
- X {
- X#ifdef NETHACK
- X if (nethackflag)
- X Msg(0, "I can't seem to find a... Hey, wait a minute! Here comes a screen now.");
- X else
- X#endif
- X Msg(0, "New screen...");
- X rflag = 0;
- X }
- X#ifdef BSDJOBS
- X brktty();
- X#endif
- X for (;;)
- X {
- X /*
- X * check to see if message line should be removed
- X */
- X if (status)
- X {
- X int time_left;
- X
- X debug("checking status...\n");
- X time_left = TimeDisplayed + (BellDisplayed ? VBellWait : MsgWait) - time((time_t *)0);
- X if (time_left > 0)
- X {
- X tv.tv_sec = time_left;
- X debug(" not yet.\n");
- X }
- X else
- X {
- X debug(" removing now.\n");
- X RemoveStatus();
- X }
- X }
- X /*
- X * check for I/O on all available I/O descriptors
- X */
- X FD_ZERO(&r);
- X FD_ZERO(&w);
- X if (inbuf_ct > 0)
- X for (n = 0; n < MAXWIN; n++)
- X#ifdef COPY_PASTE /* wrong here? jw. */
- X if (inlen[n] > 0 || (pastelen > 0 && n == ForeNum))
- X#else
- X if (inlen[n] > 0)
- X#endif
- X FD_SET(wtab[n]->ptyfd, &w);
- X if (!Detached)
- X FD_SET(0, &r);
- X for (n = WinList; n != -1; n = p->WinLink)
- X {
- X p = wtab[n];
- X if (p->active && status && !BellDisplayed && !HS)
- X continue;
- X if (p->outlen > 0)
- X continue;
- X if (in_ovl && ovl_blockfore && n == ForeNum)
- X continue;
- X FD_SET(p->ptyfd, &r);
- X }
- X FD_SET(s, &r);
- X (void) fflush(stdout);
- X if (GotSignal && !status)
- X {
- X SigHandler();
- X continue;
- X }
- X if ((nsel = select(FD_SETSIZE, &r, &w, 0, status ? &tv : (struct timeval *) 0)) < 0)
- X {
- X debug1("Bad select - errno %d\n",errno);
- X if (errno == EINTR)
- X {
- X errno = 0;
- X continue;
- X }
- X perror("select");
- X Finit(1);
- X /* NOTREACHED */
- X }
- X if (GotSignal && !status)
- X {
- X SigHandler();
- X continue;
- X }
- X /* Process a client connect attempt and message */
- X if (nsel && FD_ISSET(s, &r))
- X {
- X nsel--;
- X if (!HS)
- X RemoveStatus();
- X if (in_ovl)
- X {
- X SetOvlCurr();
- X (*ovl_process)(0,0); /* We have to abort first!! */
- X CheckScreenSize(1); /* Change fore */
- X#ifdef NETHACK
- X if (nethackflag)
- X Msg(0, "KAABLAMM!!! You triggered a land mine!");
- X else
- X#endif
- X Msg(0, "Aborted because of window change or message.");
- X }
- X else
- X CheckScreenSize(1); /* Change fore */
- X ReceiveMsg(s);
- X continue;
- X }
- X /* Read, process, and store the user input */
- X if (nsel && FD_ISSET(0, &r))
- X {
- X nsel--;
- X if (!HS)
- X RemoveStatus();
- X if (ESCseen)
- X {
- X buf[0] = Esc;
- X buflen = read(0, buf + 1, IOSIZE - 1) + 1;
- X ESCseen = 0;
- X }
- X else
- X buflen = read(0, buf, IOSIZE);
- X if (buflen < 0)
- X {
- X debug1("Read error: %d - SigHup()ing!\n", errno);
- X SigHup(SIGARG);
- X continue;
- X }
- X if (buflen == 0)
- X {
- X debug("Found EOF - SigHup()ing!\n");
- X SigHup(SIGARG);
- X continue;
- X }
- X bufp = buf;
- X if (in_ovl)
- X {
- X SetOvlCurr();
- X (*ovl_process)(&bufp, &buflen);
- X }
- X while (buflen > 0)
- X {
- X n = ForeNum;
- X len = inlen[n];
- X bufp = ProcessInput(bufp, &buflen, inbuf[n], &inlen[n],
- X sizeof *inbuf);
- X if (inlen[n] > 0 && len == 0)
- X inbuf_ct++;
- X }
- X if (inbuf_ct > 0)
- X continue;
- X }
- X if (GotSignal && !status)
- X {
- X SigHandler();
- X continue;
- X }
- X#ifdef COPY_PASTE
- X /* Write the copybuffer contents first, if any. jw. */
- X if (pastelen > 0)
- X {
- X n = ForeNum;
- X debug1("writing pastebuffer (%d)\n", pastelen);
- X tmp = wtab[n]->ptyfd;
- X if ( /* FD_ISSET(tmp,&w) && */
- X (len = write(tmp, pastebuffer,
- X pastelen > IOSIZE ? IOSIZE : pastelen)) > 0)
- X {
- X pastebuffer += len;
- X pastelen -= len;
- X debug1("%d bytes pasted\n", len);
- X if (slowpaste > 0)
- X {
- X struct timeval t;
- X
- X debug1("slowpaste %d\n", slowpaste);
- X t.tv_usec = (long) (slowpaste * 1000);
- X t.tv_sec = 0;
- X select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
- X }
- X else
- X continue;
- X }
- X /*
- X * we have to go further down, process some output, if
- X * no bytes were written...
- X */
- X }
- X#endif
- X /* Write the stored user input to the window descriptors */
- X if ( nsel && inbuf_ct > 0)
- X {
- X for (n = 0; n < MAXWIN ; n++)
- X {
- X if (inlen[n] <= 0 )
- X continue;
- X tmp = wtab[n]->ptyfd;
- X if (FD_ISSET(tmp,&w))
- X {
- X if ( (len = write(tmp, inbuf[n], inlen[n])) > 0)
- X {
- X if ((inlen[n] -= len) == 0)
- X inbuf_ct--;
- X bcopy(inbuf[n] + len, inbuf[n], inlen[n]);
- X }
- X if (--nsel == 0)
- X break;
- X }
- X }
- X }
- X if (GotSignal && !status)
- X {
- X SigHandler();
- X continue;
- X }
- X /* Read and process the output from the window descriptors */
- X for (n = WinList; n != -1; n = p->WinLink)
- X {
- X p = wtab[n];
- X if (in_ovl && ovl_blockfore && n == ForeNum)
- X continue;
- X if (p->outlen)
- X WriteString(p, p->outbuf, p->outlen);
- X else if (nsel && FD_ISSET(p->ptyfd, &r))
- X {
- X nsel--;
- X if ((len = read(p->ptyfd, buf, IOSIZE)) == -1)
- X {
- X#ifdef EWOULDBLOCK
- X if (errno == EWOULDBLOCK)
- X len = 0;
- X#endif
- X }
- X if (len > 0)
- X WriteString(p, buf, len);
- X }
- X if (p->bell == BELL_ON)
- X {
- X p->bell = BELL_DONE;
- X Msg(0, MakeWinMsg(BellString, n));
- X if (p->monitor == MON_FOUND)
- X p->monitor = MON_DONE;
- X }
- X else if (p->bell == BELL_VISUAL)
- X {
- X if (!BellDisplayed)
- X {
- X p->bell = BELL_DONE;
- X Msg(0, VisualBellString);
- X BellDisplayed = 1;
- X }
- X }
- X else if (p->monitor == MON_FOUND)
- X {
- X p->monitor = MON_DONE;
- X Msg(0, MakeWinMsg(ActivityString, n));
- X }
- X }
- X if (GotSignal && !status)
- X SigHandler();
- X#ifdef DEBUG
- X if (nsel)
- X debug1("Left over nsel: %d\n",nsel);
- X#endif
- X }
- X /* NOTREACHED */
- X}
- X
- static void SigHandler()
- X{
- X struct stat st;
- X while (GotSignal)
- X {
- X GotSignal = 0;
- X DoWait();
- X#ifdef SYSV
- X signal(SIGCLD, SigChld);
- X#endif
- X }
- X if (stat(SockPath, &st) == -1)
- X {
- X debug1("SigHandler: Yuck! cannot stat '%s'\n", SockPath);
- X if (!RecoverSocket())
- X {
- X debug("SCREEN cannot recover from corrupt Socket,bye\n");
- X Finit(1);
- X }
- X else
- X debug1("'%s' reconstructed\n", SockPath);
- X }
- X else
- X debug2("SigHandler: stat '%s' o.k. (%03o)\n", SockPath, st.st_mode);
- X}
- X
- X#ifdef DEBUG
- int FEpanic;
- X
- sig_t FEChld(SIGDEFARG)
- X{
- X FEpanic=1;
- X#ifndef SIGVOID
- X return((sig_t) 0);
- X#endif
- X}
- X#endif
- X
- static sig_t SigChld(SIGDEFARG)
- X{
- X debug("SigChld()\n");
- X GotSignal = 1;
- X#ifndef SIGVOID
- X return((sig_t) 0);
- X#endif
- X}
- X
- sig_t SigHup(SIGDEFARG)
- X{
- X debug("SigHup()\n");
- X if (auto_detach)
- X Detach(D_DETACH);
- X else
- X Finit(0);
- X#ifndef SIGVOID
- X return((sig_t) 0);
- X#endif
- X}
- X
- static sig_t SigInt(SIGDEFARG)
- X{
- X char buf[1];
- X
- X debug("SigInt()\n");
- X *buf = (char) intrc;
- X inlen[ForeNum] = 0;
- X if (fore && !in_ovl)
- X write(fore->ptyfd, buf, 1);
- X signal(SIGINT, SigInt);
- X#ifndef SIGVOID
- X return((sig_t) 0);
- X#endif
- X}
- X
- static sig_t CoreDump(sig)
- int sig;
- X{
- X setgid(getgid());
- X setuid(getuid());
- X unlink("core");
- X fprintf(stderr, "\r\n[screen caught signal %d. (core dumped)]\r\n", sig);
- X fflush(stderr);
- X Kill(AttacherPid, SIG_BYE);
- X abort();
- X#ifndef SIGVOID
- X return((sig_t) 0);
- X#endif
- X}
- X
- static void DoWait()
- X{
- X register int n, next, pid;
- X#ifdef BSDWAIT
- X union wait wstat;
- X#else
- X int wstat;
- X#endif
- X
- X#ifdef BSDJOBS
- X# ifndef BSDWAIT
- X while ((pid = waitpid(-1, &wstat, WNOHANG | WUNTRACED)) > 0)
- X# else
- X while ((pid = wait3(&wstat, WNOHANG | WUNTRACED, (struct rusage *) 0)) > 0)
- X# endif
- X#else /* BSDJOBS */
- X while ((pid = wait(&wstat)) < 0)
- X if (errno != EINTR)
- X break;
- X if (pid >= 0)
- X#endif /* BSDJOBS */
- X {
- X for (n = WinList; n != -1; n = next)
- X {
- X next = wtab[n]->WinLink;
- X if (pid == wtab[n]->wpid)
- X {
- X#ifdef BSDJOBS
- X if (WIFSTOPPED(wstat))
- X {
- X Msg(0, "Child has been stopped, restarting.");
- X debug1("WIFSTOPPED: %d SIGCONT\n", wtab[n]->wpid);
- X if (killpg(wtab[n]->wpid, SIGCONT))
- X kill(wtab[n]->wpid, SIGCONT);
- X }
- X else
- X#endif
- X KillWindow(n);
- X }
- X }
- X }
- X}
- X
- void KillWindow(n)
- int n;
- X{
- X register int i;
- X /*
- X * Remove window from linked list.
- X */
- X if (n == WinList) /* WinList = ForeNum */
- X {
- X RemoveStatus();
- X WinList = fore->WinLink;
- X fore = 0;
- X }
- X else
- X {
- X i = WinList;
- X while (wtab[i]->WinLink != n)
- X i = wtab[i]->WinLink;
- X wtab[i]->WinLink = wtab[n]->WinLink;
- X }
- X FreeWindow(wtab[n]);
- X wtab[n] = 0;
- X if (inlen[n] > 0)
- X {
- X inlen[n] = 0;
- X inbuf_ct--;
- X }
- X /*
- X * If the foreground window disappeared check the head of the linked list
- X * of windows for the most recently used window. If no window is alive at
- X * all, exit.
- X */
- X if (WinList == -1)
- X Finit(0);
- X if (!fore)
- X SwitchWindow(WinList);
- X}
- X
- static sig_t Finit(i)
- int i;
- X{
- X register int n, next;
- X
- X#ifdef SYSV
- X signal(SIGCLD, SIG_IGN);
- X#else
- X signal(SIGCHLD, SIG_IGN);
- X#endif
- X signal(SIGHUP, SIG_IGN);
- X debug1("Finit(%d);\n", i);
- X for (n = WinList; n != -1; n = next)
- X {
- X next = wtab[n]->WinLink;
- X FreeWindow(wtab[n]);
- X }
- X FinitTerm();
- X SetTTY(0, &OldMode);
- X#ifdef UTMPOK
- X RestoreLoginSlot();
- X#endif
- X printf("\n[screen is terminating]\n");
- X freetty();
- X if (ServerSocket != -1)
- X {
- X debug1("we unlink(%s)\n", SockPath);
- X (void) unlink(SockPath);
- X }
- X Kill(AttacherPid, SIG_BYE);
- X exit(i);
- X#ifndef SIGVOID
- X return((sig_t) 0);
- X#endif
- X}
- X
- void
- eexit(e)
- int e;
- X{
- X if (ServerSocket != -1)
- X {
- X debug1("we unlink(%s)\n", SockPath);
- X (void) unlink(SockPath);
- X }
- X exit(e);
- X}
- X
- static void InitKeytab()
- X{
- X register int i;
- X
- X for (i = 0; i < sizeof(ktab)/sizeof(*ktab); i++)
- X ktab[i].type = KEY_IGNORE;
- X
- X ktab['h'].type = ktab[Ctrl('h')].type = KEY_HARDCOPY;
- X#ifdef BSDJOBS
- X ktab['z'].type = ktab[Ctrl('z')].type = KEY_SUSPEND;
- X#endif
- X ktab['c'].type = ktab[Ctrl('c')].type = KEY_SHELL;
- X ktab[' '].type = ktab[Ctrl(' ')].type =
- X ktab['n'].type = ktab[Ctrl('n')].type = KEY_NEXT;
- X ktab['-'].type = ktab['p'].type = ktab[Ctrl('p')].type = KEY_PREV;
- X ktab['k'].type = ktab[Ctrl('k')].type = KEY_KILL;
- X ktab['l'].type = ktab[Ctrl('l')].type = KEY_REDISPLAY;
- X ktab['w'].type = ktab[Ctrl('w')].type = KEY_WINDOWS;
- X ktab['v'].type = ktab[Ctrl('v')].type = KEY_VERSION;
- X ktab['q'].type = ktab[Ctrl('q')].type = KEY_XON;
- X ktab['s'].type = ktab[Ctrl('s')].type = KEY_XOFF;
- X ktab['t'].type = ktab[Ctrl('t')].type = KEY_TIME;
- X ktab['i'].type = ktab[Ctrl('i')].type = KEY_INFO;
- X ktab['m'].type = ktab[Ctrl('m')].type = KEY_LASTMSG;
- X ktab['A'].type = KEY_AKA, ktab['A'].args = NULL;
- X ktab['L'].type = KEY_LOGIN;
- X ktab[','].type = KEY_LICENSE;
- X ktab['W'].type = KEY_WIDTH;
- X ktab['.'].type = KEY_TERMCAP;
- X ktab[Ctrl('\\')].type = KEY_QUIT;
- X ktab['d'].type = ktab[Ctrl('d')].type = KEY_DETACH;
- X ktab['r'].type = ktab[Ctrl('r')].type = KEY_WRAP;
- X ktab['f'].type = ktab[Ctrl('f')].type = KEY_FLOW;
- X ktab['/'].type = KEY_AUTOFLOW;
- X ktab['C'].type = KEY_CLEAR;
- X ktab['Z'].type = KEY_RESET;
- X ktab['H'].type = KEY_LOGTOGGLE;
- X if (Esc != MetaEsc)
- X ktab[Esc].type = KEY_OTHER;
- X else
- X ktab[Esc].type = KEY_IGNORE;
- X ktab['M'].type = KEY_MONITOR;
- X ktab['?'].type = KEY_HELP;
- X for (i = 0; i <= 9; i++)
- X ktab['0' + i].type = (enum keytype) (i + (int)KEY_0);
- X ktab[Ctrl('G')].type = KEY_VBELL;
- X ktab[':'].type = KEY_COLON;
- X#ifdef COPY_PASTE
- X ktab['['].type = ktab[Ctrl('[')].type = KEY_COPY;
- X ktab[']'].type = ktab[Ctrl(']')].type = KEY_PASTE;
- X ktab['{'].type = KEY_HISTORY; /* } */
- X ktab['>'].type = KEY_WRITE_BUFFER;
- X ktab['<'].type = KEY_READ_BUFFER;
- X ktab['='].type = KEY_REMOVE_BUFFERS;
- X#endif
- X#ifdef POW_DETACH
- X ktab['D'].type = KEY_POW_DETACH;
- X#endif
- X#ifdef LOCK
- X ktab['x'].type = ktab[Ctrl('x')].type = KEY_LOCK;
- X#endif
- X}
- X
- X/*
- X * this is a braindamaged hack: if (obuf == NULL) then we provided
- X * a key_type as a second char in ibuf. not a key.
- X */
- char *ProcessInput(ibuf, pilen, obuf, polen, obuf_size)
- char *ibuf, *obuf;
- register int *pilen, *polen, obuf_size;
- X{
- X register int n;
- X register enum keytype k;
- X register char *s, *p;
- X char buf[2];
- X int newwidth;
- X
- X if (!obuf)
- X obuf_size = 0;
- X
- X for (s = ibuf, p = obuf + *polen; *pilen > 0; --*pilen, s++)
- X {
- X if (*s == Esc)
- X {
- X debug2("'%c %c ", s[0], s[1]);
- X debug2("%c %c' ", s[2], s[3]);
- X if (*pilen > 1)
- X {
- X --*pilen;
- X s++;
- X#if defined(GOULD_NP1)
- X k = (obuf)?(ktab[*s].type):(enum keytype)(int)(*s);
- X#else
- X k = (obuf)?(ktab[*s].type):(enum keytype)(*s);
- X#endif
- X debug2("Processinput C-A %02x '%c' ", k, k);
- X debug1("%s\n", (obuf)?"std":"NOOBUF");
- X if (*s == MetaEsc)
- X {
- X if (*polen < obuf_size)
- X {
- X *p++ = Esc;
- X ++*polen;
- X }
- X }
- X else if ((int)k >= (int)KEY_0 && (int)k <= (int)KEY_9)
- X SwitchWindow((int)k - (int)KEY_0);
- X else
- X switch (k)
- X {
- X case KEY_TERMCAP:
- X WriteFile(DUMP_TERMCAP);
- X break;
- X case KEY_HARDCOPY:
- X WriteFile(DUMP_HARDCOPY);
- X break;
- X case KEY_LOGTOGGLE:
- X LogToggle();
- X break;
- X#ifdef BSDJOBS
- X case KEY_SUSPEND:
- X *pilen = 0;
- X Detach(D_STOP);
- X break;
- X#endif
- X case KEY_SHELL:
- X debug("calling MakeWindow with shell\n");
- X MakeWindow(shellaka, ShellArgs,
- X 0, flowctl, 0, (char *) 0, loginflag, -1, 0);
- X break;
- X case KEY_NEXT:
- X if (MoreWindows())
- X SwitchWindow(NextWindow());
- X break;
- X case KEY_PREV:
- X if (MoreWindows())
- X SwitchWindow(PreviousWindow());
- X break;
- X case KEY_KILL:
- X KillWindow(n = ForeNum);
- X#ifdef NETHACK
- X if (nethackflag)
- X Msg(0, "You destroy poor window %d", n);
- X#endif
- X break;
- X case KEY_QUIT:
- X Finit(0);
- X /* NOTREACHED */
- X case KEY_DETACH:
- X *pilen = 0;
- X Detach(D_DETACH);
- X break;
- X#ifdef POW_DETACH
- X case KEY_POW_DETACH:
- X *pilen = 0;
- X buf[0] = *s;
- X buf[1] = '\0';
- X Msg(0, buf);
- X read(0, buf, 1);
- X if (*buf == *s)
- X Detach(D_POWER); /* detach and kill Attacher's
- X * parent */
- X else
- X {
- X write(1, "\007", 1);
- X RemoveStatus();
- X#ifdef NETHACK
- X if (nethackflag)
- X Msg(0, "The blast of disintegration whizzes by you!");
- X#endif
- X }
- X break;
- X#endif
- X case KEY_REDISPLAY:
- X Activate();
- X break;
- X case KEY_WINDOWS:
- X ShowWindows();
- X break;
- X case KEY_VERSION:
- X Msg(0, "screen %d.%.2d.%.2d%s (%s) %s",REV, VERS, PATCHLEVEL, STATE, ORIGIN, DATE);
- X break;
- X case KEY_TIME:
- X ShowTime();
- X break;
- X case KEY_INFO:
- X ShowInfo();
- X break;
- X case KEY_OTHER:
- X if (MoreWindows())
- X SwitchWindow(fore->WinLink);
- X break;
- X case KEY_XON:
- X if (*polen < obuf_size)
- X {
- X *p++ = Ctrl('q');
- X ++*polen;
- X }
- X break;
- X case KEY_XOFF:
- X if (*polen < obuf_size)
- X {
- X *p++ = Ctrl('s');
- X ++*polen;
- X }
- X break;
- X#ifdef LOCK
- X case KEY_LOCK:
- X Detach(D_LOCK); /* do it micha's way */
- X break;
- X#endif
- X case KEY_WIDTH:
- X if (Z0 || WS)
- X {
- X if (fore->width == Z0width)
- X newwidth=Z1width;
- X else if (fore->width == Z1width)
- X newwidth=Z0width;
- X else if (fore->width > (Z0width+Z1width)/2)
- X newwidth=Z0width;
- X else
- X newwidth=Z1width;
- X ChangeWindowSize(fore, newwidth, fore->height);
- X Activate();
- X }
- X else
- X Msg(0, "Your termcap does not specify how to change the terminal's width.");
- X break;
- X case KEY_LOGIN:
- X SlotToggle(0);
- X break;
- X case KEY_AKA:
- X if (!ktab[*s].args)
- X InputAKA();
- X else
- X strncpy(fore->cmd + fore->akapos, ktab[*s].args[0], 20);
- X break;
- X case KEY_COLON:
- X InputColon();
- X break;
- X case KEY_LASTMSG:
- X Msg(0, "%s", LastMsg);
- X break;
- X case KEY_SET:
- X DoSet(ktab[*s].args);
- X break;
- X case KEY_SCREEN:
- X debug3("KEY_SCREEN DoSc(, ktab[%d].args(='%s','%s')...)\n",
- X *s, ktab[*s].args[0], ktab[*s].args[1]);
- X DoScreen("key", ktab[*s].args);
- X break;
- X case KEY_CREATE:
- X debug2("KEY_CREATE MaWi(0, ktab[%d].args(='%s')...)\n",
- X *s, ktab[*s].args);
- X MakeWindow((char *) 0, ktab[*s].args,
- X 0, flowctl, 0, (char *) 0, loginflag, -1, 0);
- X break;
- X case KEY_WRAP:
- X fore->wrap = !fore->wrap;
- X Msg(0, "%cwrap", fore->wrap ? '+' : '-');
- X break;
- X case KEY_FLOW:
- X ToggleFlow();
- X goto flow_msg;
- X case KEY_AUTOFLOW:
- X if ((fore->autoflow = !fore->autoflow) != 0
- X && fore->flow == fore->keypad)
- X ToggleFlow();
- X flow_msg:
- X Msg(0, "%cflow%s", fore->flow ? '+' : '-',
- X fore->autoflow ? "(auto)" : "");
- X break;
- X case KEY_CLEAR:
- X if (fore->state == LIT)
- X WriteString(fore, "\033[H\033[J", 6);
- X break;
- X case KEY_RESET:
- X if (fore->state == LIT)
- X WriteString(fore, "\033c", 2);
- X break;
- X case KEY_MONITOR:
- X if (fore->monitor == MON_OFF)
- X {
- X fore->monitor = MON_ON;
- X Msg(0,
- X "Window %d is now being monitored for all activity.",
- X ForeNum);
- X }
- X else
- X {
- X fore->monitor = MON_OFF;
- X Msg(0,
- X "Window %d is no longer being monitored for activity.",
- X ForeNum);
- X }
- X break;
- X case KEY_HELP:
- X display_help();
- X break;
- X case KEY_LICENSE:
- X display_copyright();
- X break;
- X#ifdef COPY_PASTE
- X case KEY_COPY:
- X /* SetOvlCurr(); */
- X (void) MarkRoutine(PLAIN);
- X break;
- X case KEY_HISTORY:
- X /* SetOvlCurr(); */
- X if (MarkRoutine(TRICKY))
- X if (copybuffer != NULL)
- X {
- X pastelen = copylen;
- X pastebuffer = copybuffer;
- X debug1("history new copylen: %d\n", pastelen);
- X }
- X break;
- X case KEY_PASTE:
- X if (copybuffer == NULL)
- X {
- X#ifdef NETHACK
- X if (nethackflag)
- X Msg(0, "Nothing happens.");
- X else
- X#endif
- X Msg(0, "empty buffer");
- X copylen = 0;
- X break;
- X }
- X pastelen = copylen;
- X pastebuffer = copybuffer;
- X break;
- X case KEY_WRITE_BUFFER:
- X if (copybuffer == NULL)
- X {
- X#ifdef NETHACK
- X if (nethackflag)
- X Msg(0, "Nothing happens.");
- X else
- X#endif
- X Msg(0, "empty buffer");
- X copylen = 0;
- X break;
- X }
- X WriteFile(DUMP_EXCHANGE);
- X break;
- X case KEY_READ_BUFFER:
- X ReadFile();
- X break;
- X case KEY_REMOVE_BUFFERS:
- X KillBuffers();
- X break;
- X#endif /* COPY_PASTE */
- X case KEY_VBELL:
- X if (visual_bell)
- X {
- X visual_bell = 0;
- X Msg(0, ":vbell off");
- X }
- X else
- X {
- X visual_bell = 1;
- X Msg(0, ":vbell on");
- X }
- X break;
- X default:
- X break;
- X }
- X }
- X else
- X ESCseen = 1;
- X --*pilen;
- X s++;
- X break;
- X }
- X else if (*polen < obuf_size)
- X {
- X *p++ = *s;
- X ++*polen;
- X }
- X }
- X return (s);
- X}
- X
- X/* Send a terminal report as if it were typed. */
- void
- Report(wp, fmt, n1, n2)
- struct win *wp;
- char *fmt;
- int n1, n2;
- X{
- X register int n, len;
- X char rbuf[40];
- X
- X sprintf(rbuf, fmt, n1, n2);
- X len = strlen(rbuf);
- X
- X for (n = 0; n < MAXWIN; n++)
- X {
- X if (wp == wtab[n])
- X {
- X if (inlen[n] + len <= sizeof *inbuf)
- X {
- X bcopy(rbuf, inbuf[n] + inlen[n], len);
- X if (inlen[n] == 0)
- X inbuf_ct++;
- X inlen[n] += len;
- X }
- X break;
- X }
- X }/* for */
- X}
- X
- void
- SwitchWindow(n)
- int n;
- X{
- X debug1("SwitchWindow %d\n", n);
- X if (!wtab[n])
- X {
- X ShowWindows();
- X return;
- X }
- X if (wtab[n] == fore)
- X {
- X Msg(0, "This IS window %d.", n);
- X return;
- X }
- X SetForeWindow(n);
- X if (!Detached && !in_ovl)
- X Activate();
- X}
- X
- static void SetForeWindow(n)
- int n;
- X{
- X /*
- X * If we come from another window, make it inactive.
- X */
- X if (fore)
- X fore->active = 0;
- X ForeNum = n;
- X fore = wtab[n];
- X if (!Detached && !in_ovl)
- X fore->active = 1;
- X /*
- X * Place the window at the head of the most-recently-used list.
- X */
- X if ((n = WinList) != ForeNum)
- X {
- X /*
- X * we had a bug here. we sometimes ran into n = -1; and crashed.
- X * (this is not the perfect fix. "if(...) break;" inserted. jw.)
- X */
- X while (wtab[n]->WinLink != ForeNum)
- X {
- X if (wtab[n]->WinLink == -1)
- X break;
- X n = wtab[n]->WinLink;
- X }
- X wtab[n]->WinLink = fore->WinLink;
- X fore->WinLink = WinList;
- X WinList = ForeNum;
- X }
- X}
- X
- static int NextWindow()
- X{
- X register struct win **pp;
- X
- X for (pp = wtab + ForeNum + 1; pp != wtab + ForeNum; ++pp)
- X {
- X if (pp == wtab + MAXWIN)
- X pp = wtab;
- X if (*pp)
- X break;
- X }
- X return pp - wtab;
- X}
- X
- static int PreviousWindow()
- X{
- X register struct win **pp;
- X
- X for (pp = wtab + ForeNum - 1; pp != wtab + ForeNum; --pp)
- X {
- X if (pp < wtab)
- X pp = wtab + MAXWIN - 1;
- X if (*pp)
- X break;
- X }
- X return pp - wtab;
- X}
- X
- static int MoreWindows()
- X{
- X if (fore->WinLink != -1)
- X return 1;
- X Msg(0, "No other window.");
- X return 0;
- X}
- X
- static void FreeWindow(wp)
- struct win *wp;
- X{
- X#ifdef UTMPOK
- X RemoveUtmp(wp);
- X#endif
- X#ifdef SUIDROOT
- X (void) chmod(wp->tty, 0666);
- X (void) chown(wp->tty, 0, 0);
- X#endif
- X close(wp->ptyfd);
- X if (wp->logfp != NULL)
- X fclose(wp->logfp);
- X ChangeWindowSize(wp, 0, 0);
- X Free(wp);
- X}
- X
- int
- MakeWindow(prog, args, aflag, flowflag, StartAt, dir, lflag, histheight, term)
- char *prog, **args, *dir;
- int aflag, flowflag, StartAt, lflag, histheight;
- char *term; /* if term is nonzero we assume it "vt100" or the like.. */
- X{
- X register struct win **pp, *p;
- X register int n, f;
- X int tf, tlflag;
- X char ebuf[10];
- X#ifndef TIOCSWINSZ
- X char libuf[20], cobuf[20];
- X#endif
- X char tebuf[25];
- X
- X pp = wtab + StartAt;
- X do
- X {
- X if (*pp == 0)
- X break;
- X if (++pp == wtab + MAXWIN)
- X pp = wtab;
- X } while (pp != wtab + StartAt);
- X if (*pp)
- X {
- X Msg(0, "No more windows.");
- X return -1;
- X }
- X
- X if (((tlflag = lflag) == -1) && ((tlflag = loginflag) == -1))
- X tlflag = LOGINDEFAULT;
- X
- X#ifdef USRLIMIT
- X /*
- X * Count current number of users, if logging windows in.
- X */
- X if (tlflag == 1 && CountUsers() >= USRLIMIT)
- X {
- X Msg(0, "User limit reached. Window will not be logged in.");
- X tlflag = 0;
- X }
- X#endif
- X n = pp - wtab;
- X debug1("Makewin creating %d\n", n);
- X if ((f = OpenPTY()) == -1)
- X {
- X Msg(0, "No more PTYs.");
- X return -1;
- X }
- X#ifdef SYSV
- X (void) fcntl(f, F_SETFL, O_NDELAY);
- X#else
- X (void) fcntl(f, F_SETFL, FNDELAY);
- X#endif
- X if ((p = (struct win *) malloc(sizeof(struct win))) == 0)
- X {
- X close(f);
- X Msg_nomem;
- X return -1;
- X }
- X bzero((char *) p, (int) sizeof(struct win));
- X p->ptyfd = f;
- X p->aflag = aflag;
- X if (!flowflag)
- X flowflag = flowctl;
- X p->flow = (flowflag != 1);
- X p->autoflow = (flowflag == 3);
- X if (!prog)
- X prog = Filename(args[0]);
- X strncpy(p->cmd, prog, MAXSTR - 1);
- X if ((prog = rindex(p->cmd, '|')) != NULL)
- X {
- X *prog++ = '\0';
- X prog += strlen(prog);
- X p->akapos = prog - p->cmd;
- X p->autoaka = 0;
- X }
- X else
- X p->akapos = 0;
- X p->monitor = default_monitor;
- X strncpy(p->tty, TtyName, MAXSTR - 1);
- X#ifdef SUIDROOT
- X (void) chown(TtyName, real_uid, real_gid);
- X# ifdef UTMPOK
- X (void) chmod(TtyName, tlflag ? TtyMode : (TtyMode & ~022));
- X# else
- X (void) chmod(TtyName, TtyMode);
- X# endif
- X#endif
- X
- X if (histheight < 0)
- X histheight = default_histheight;
- X if (ChangeWindowSize(p, default_width, default_height))
- X {
- X FreeWindow(p);
- X return -1;
- X }
- X ChangeScrollback(p, histheight, default_width);
- X ResetScreen(p);
- X debug("forking...\n");
- X switch (p->wpid = fork())
- X {
- X case -1:
- X Msg(errno, "fork");
- X FreeWindow(p);
- X return -1;
- X case 0:
- X signal(SIGHUP, SIG_DFL);
- X signal(SIGINT, SIG_DFL);
- X signal(SIGQUIT, SIG_DFL);
- X signal(SIGTERM, SIG_DFL);
- X#ifdef BSDJOBS
- X signal(SIGTTIN, SIG_DFL);
- X signal(SIGTTOU, SIG_DFL);
- X#else
- X setpgrp();
- X#endif
- X setuid(real_uid);
- X setgid(real_gid);
- X if (dir && chdir(dir) == -1)
- X {
- X SendErrorMsg("Cannot chdir to %s: %s", dir, sys_errlist[errno]);
- X eexit(1);
- X }
- X
- X freetty();
- X#ifdef SYSV
- X setpgrp();
- X#endif
- X if ((tf = open(TtyName, O_RDWR)) == -1)
- X {
- X SendErrorMsg("Cannot open %s: %s", TtyName, sys_errlist[errno]);
- X eexit(1);
- X }
- X#ifdef SVR4
- X if (ioctl(tf, I_PUSH, "ptem"))
- X {
- X SendErrorMsg("Cannot I_PUSH ptem %s %s", TtyName, sys_errlist[errno]);
- X eexit(1);
- X }
- X if (ioctl(tf, I_PUSH, "ldterm"))
- X {
- X SendErrorMsg("Cannot I_PUSH ldterm %s %s", TtyName, sys_errlist[errno]);
- X eexit(1);
- X }
- X if (ioctl(tf, I_PUSH, "ttcompat"))
- X {
- X SendErrorMsg("Cannot I_PUSH ttcompat %s %s", TtyName, sys_errlist[errno]);
- X eexit(1);
- X }
- X#endif
- X (void) dup2(tf, 0);
- X (void) dup2(tf, 1);
- X (void) dup2(tf, 2);
- X#ifdef DEBUG
- X dfp = stderr;
- X#endif
- X#ifdef SYSV
- X for (f = NOFILE - 1; f > 2; f--)
- X close(f);
- X#else
- X for (f = getdtablesize() - 1; f > 2; f--)
- X close(f);
- X#endif
- X fgtty();
- X#ifdef TIOCSWINSZ
- X glwz.ws_col=p->width;
- X glwz.ws_row=p->height;
- X (void) ioctl(0, TIOCSWINSZ, &glwz);
- X#else
- X sprintf(libuf, "LINES=%d", p->height);
- X sprintf(cobuf, "COLUMNS=%d", p->width);
- X NewEnv[4] = libuf;
- X NewEnv[5] = cobuf;
- X#endif
- X SetTTY(0, &OldMode);
- X if (aflag)
- X NewEnv[2] = MakeTermcap(1);
- X else
- X NewEnv[2] = Termcap;
- X if (term && *term && strcmp(screenterm, term) &&
- X ((unsigned)strlen(term) < 20))
- X {
- X char *s1, *s2, tl;
- X
- X sprintf(tebuf, "TERM=%s", term);
- X debug2("Makewindow %d with %s\n", n, tebuf);
- X tl = strlen(term);
- X NewEnv[1] = tebuf;
- X if (s1 = index(Termcap, '|'))
- X {
- X if (s2 = index(++s1, '|'))
- X {
- X if (strlen(Termcap) - (s2 - s1) + tl < 1024)
- X {
- X bcopy(s2, s1 + tl, strlen(s2) + 1);
- X bcopy(term, s1, tl);
- X }
- X }
- X }
- X }
- X sprintf(ebuf, "WINDOW=%d", n);
- X NewEnv[3] = ebuf;
- X
- X execvpe(*args, args, NewEnv);
- X SendErrorMsg("Cannot exec %s: %s", *args, sys_errlist[errno]);
- X exit(1);
- X } /* end fork switch */
- X /*
- X * Place the newly created window at the head of the most-recently-used list.
- X */
- X *pp = p;
- X p->WinLink = WinList;
- X WinList = n;
- X HasWindow = 1;
- X#ifdef UTMPOK
- X debug1("MakeWindow will %slog in.\n", tlflag?"":"not ");
- X if (tlflag == 1)
- X SetUtmp(p, n);
- X else
- X p->slot = (slot_t) -1;
- X#endif
- X SetForeWindow(n);
- X Activate();
- X return n;
- X}
- X
- static void execvpe(prog, args, env)
- char *prog, **args, **env;
- X{
- X register char *path, *p;
- X char buf[1024];
- X char *shargs[MAXARGS + 1];
- X register int i, eaccess = 0;
- X
- X if (prog[0] == '/')
- X path = "";
- X else if ((path = getenv("PATH")) == 0)
- X path = DefaultPath;
- X do
- X {
- X p = buf;
- X while (*path && *path != ':')
- X *p++ = *path++;
- X if (p > buf)
- X *p++ = '/';
- X strcpy(p, prog);
- X if (*path)
- X ++path;
- X execve(buf, args, env);
- X switch (errno)
- X {
- X case ENOEXEC:
- X shargs[0] = DefaultShell;
- X shargs[1] = buf;
- X for (i = 1; (shargs[i + 1] = args[i]) != NULL; ++i)
- X ;
- X execve(DefaultShell, shargs, env);
- X return;
- X case EACCES:
- X eaccess = 1;
- X break;
- X case ENOMEM:
- X case E2BIG:
- X case ETXTBSY:
- X return;
- X }
- X } while (*path);
- X if (eaccess)
- X errno = EACCES;
- X}
- X
- X
- static void LogToggle()
- X{
- X char buf[1024];
- X
- X sprintf(buf, "screenlog.%d", ForeNum);
- X if (fore->logfp != NULL)
- X {
- X Msg(0, "Logfile \"%s\" closed.", buf);
- X fclose(fore->logfp);
- X fore->logfp = NULL;
- X return;
- X }
- X if ((fore->logfp = secfopen(buf, "a")) == NULL)
- X {
- X Msg(errno, "Error opening logfile \"%s\"", buf);
- X return;
- X }
- X Msg(0, "%s logfile \"%s\"", ftell(fore->logfp) ? "Appending to" : "Creating", buf);
- X}
- X
- X#ifdef NOREUID
- static int UserPID;
- X#endif
- static int UserSTAT;
- X
- int UserContext()
- X{
- X#ifdef NOREUID
- X if (eff_uid == real_uid)
- X return(1);
- X debug("UserContext: forking.\n");
- X switch (UserPID = fork())
- X {
- X case -1:
- X Msg(errno, "fork");
- X return -1;
- X case 0:
- X signal(SIGHUP, SIG_DFL);
- X signal(SIGINT, SIG_IGN);
- X signal(SIGQUIT, SIG_DFL);
- X signal(SIGTERM, SIG_DFL);
- X# ifdef BSDJOBS
- X signal(SIGTTIN, SIG_DFL);
- X signal(SIGTTOU, SIG_DFL);
- X# endif
- X setuid(real_uid);
- X setgid(real_gid);
- X return 1;
- X default:
- X return 0;
- X }
- X#else
- X setreuid(eff_uid, real_uid);
- X setregid(eff_gid, real_gid);
- X return 1;
- X#endif
- X}
- X
- void
- UserReturn(val)
- int val;
- X{
- X#if defined(NOREUID)
- X if (eff_uid == real_uid)
- X UserSTAT = val;
- X else
- X exit(val);
- X#else
- X setreuid(real_uid, eff_uid);
- X setregid(real_gid, eff_gid);
- X UserSTAT = val;
- X#endif
- X}
- X
- int UserStatus()
- X{
- X#ifdef NOREUID
- X int i;
- X# ifdef BSDWAIT
- X union wait wstat;
- X# else
- X int wstat;
- X# endif
- X
- X if (eff_uid == real_uid)
- X return UserSTAT;
- X if (UserPID < 0)
- X return -1;
- X while ((errno = 0, i = wait(&wstat)) != UserPID)
- X if (i < 0 && errno != EINTR)
- X break;
- X if (i == -1)
- X return -1;
- X return (WEXITSTATUS(wstat));
- X#else
- X return UserSTAT;
- X#endif
- X}
- X
- static void ShowWindows()
- X{
- X char buf[1024];
- X register char *s;
- X register struct win **pp, *p;
- X register int i, OtherNum = fore->WinLink;
- X register char *cmd;
- X
- X for (i = 0, s = buf, pp = wtab; pp < wtab + MAXWIN; ++i, ++pp)
- X {
- X if ((p = *pp) == 0)
- X continue;
- X
- X if (p->akapos)
- X {
- X if (*(p->cmd + p->akapos) && *(p->cmd + p->akapos - 1) != ':')
- X cmd = p->cmd + p->akapos;
- X else
- X cmd = p->cmd + strlen(p->cmd) + 1;
- X }
- X else
- X cmd = p->cmd;
- X if (s - buf + 5 + (unsigned)strlen(cmd) > fore->width - 1)
- X break;
- X if (s > buf)
- X {
- X *s++ = ' ';
- X *s++ = ' ';
- X }
- X *s++ = i + '0';
- X if (i == ForeNum)
- X *s++ = '*';
- X else if (i == OtherNum)
- X *s++ = '-';
- X if (p->monitor == MON_DONE)
- X *s++ = '@';
- X if (p->bell == BELL_DONE)
- X *s++ = '!';
- X#ifdef UTMPOK
- X if (p->slot != (slot_t) 0 && p->slot != (slot_t) -1)
- X *s++ = '$';
- X#endif
- X if (p->logfp != NULL)
- X {
- X strcpy(s, "(L)");
- X s += 3;
- X }
- X *s++ = ' ';
- X strcpy(s, cmd);
- X s += strlen(s);
- X if (i == ForeNum)
- X {
- X /*
- X * this is usually done by Activate(), but when looking
- X * on your current window, you may get annoyed, as there is still
- X * that temporal '!' and '@' displayed.
- X * So we remove that after displaying it once.
- X */
- X p->bell = BELL_OFF;
- X if (p->monitor != MON_OFF)
- X p->monitor = MON_ON;
- X }
- X }
- X *s++ = ' ';
- X *s = '\0';
- X Msg(0, "%s", buf);
- X}
- X
- X#ifdef LOADAV_3LONGS
- extern long loadav[3];
- X#else
- X# ifdef LOADAV_4LONGS
- extern long loadav[4];
- X# else
- extern double loadav[3];
- X# endif
- X#endif
- extern avenrun;
- X
- static void ShowTime()
- X{
- X char buf[512];
- X#ifdef LOADAV
- X char *p;
- X#endif
- X struct tm *tp;
- X time_t now;
- X
- X (void) time(&now);
- X tp = localtime(&now);
- X sprintf(buf, "%2d:%02.2d:%02.2d %s", tp->tm_hour, tp->tm_min, tp->tm_sec,
- X HostName);
- X#ifdef LOADAV
- X if (avenrun && GetAvenrun())
- X {
- X p = buf + strlen(buf);
- X#ifdef LOADAV_3LONGS
- X sprintf(p, " %2.2f %2.2f %2.2f", (double) loadav[0] / FSCALE,
- X (double) loadav[1] / FSCALE, (double) loadav[2] / FSCALE);
- X#else
- X#ifdef LOADAV_4LONGS
- X sprintf(p, " %2.2f %2.2f %2.2f %2.2f", (double) loadav[0] / 100,
- X (double) loadav[1] / 100, (double) loadav[2] / 100,
- X (double) loadav[3] / 100);
- X#else
- X sprintf(p, " %2.2f %2.2f %2.2f", loadav[0], loadav[1], loadav[2]);
- X#endif
- X#endif
- X }
- X#endif
- X Msg(0, "%s", buf);
- X}
- X
- static void ShowInfo()
- X{
- X char buf[512], *p;
- X register struct win *wp = fore;
- X register int i;
- X
- X sprintf(buf, "(%d,%d)/(%d,%d)+%d %cflow%s %cins %corg %cwrap %capp %clog %cmon",
- X wp->x + 1, wp->y + 1, wp->width, wp->height,
- X wp->histheight,
- X wp->flow ? '+' : '-', wp->autoflow ? "(auto)" : "",
- X wp->insert ? '+' : '-', wp->origin ? '+' : '-',
- X wp->wrap ? '+' : '-', wp->keypad ? '+' : '-',
- X (wp->logfp != NULL) ? '+' : '-',
- X (wp->monitor != MON_OFF) ? '+' : '-');
- X if (ISO2022)
- X {
- X p = buf + strlen(buf);
- X sprintf(p, " G%1d [", wp->LocalCharset);
- X for (i = 0; i < 4; i++)
- X p[i + 5] = wp->charsets[i] ? wp->charsets[i] : 'B';
- X p[9] = ']';
- X p[10] = '\0';
- X }
- X Msg(0, "%s", buf);
- X}
- X
- X#if defined(sequent) || defined(_SEQUENT_) || defined(SVR4)
- X
- static int OpenPTY()
- X{
- X char *m, *s;
- X register int f;
- X# ifdef SVR4
- X char *ptsname();
- X sig_t (*sigcld)();
- X
- X if ((f = open("/dev/ptmx", O_RDWR)) == -1)
- X return(-1);
- X
- X /*
- X * SIGCLD set to SIG_DFL for grantpt() because it fork()s and
- X * exec()s pt_chmod
- X */
- X sigcld = signal(SIGCLD, SIG_DFL);
- X
- X if ((m = ptsname(f)) == NULL || unlockpt(f) || grantpt(f))
- X {
- X signal(SIGCLD, sigcld);
- X close(f);
- X return(-1);
- X }
- X signal(SIGCLD, sigcld);
- X strncpy(TtyName, m, sizeof TtyName);
- X# else /* SVR4 */
- X if ((f = getpseudotty(&s, &m)) < 0)
- X return(-1);
- X strncpy(PtyName, m, sizeof PtyName);
- X strncpy(TtyName, s, sizeof TtyName);
- X# endif /* SVR4 */
- X# ifdef POSIX
- X tcflush(f,TCIOFLUSH);
- X# else
- X (void) ioctl(f, TIOCFLUSH, (char *) 0);
- X# endif
- X# ifdef LOCKPTY
- X (void) ioctl(f, TIOCEXCL, (char *) 0);
- X# endif
- X return (f);
- X}
- X
- X#else /* defined(sequent) || defined(_SEQUENT_) || defined(SVR4) */
- X# if defined(MIPS)
- X# if !defined(SGI)
- X
- static int OpenPTY()
- X{
- X register char *p, *l, *d;
- X register f, tf;
- X register my_minor;
- X struct stat buf;
- X
- X strcpy(PtyName, PtyProto);
- X for (p = PtyName; *p != 'X'; ++p)
- X ;
- X for (l = "zyxwvutsrqp"; *p = *l; ++l)
- X {
- X for (d = "0123456789abcdef"; p[1] = *d; ++d)
- X {
- X if ((f = open(PtyName, O_RDWR)) != -1)
- X {
- X fstat(f, &buf);
- X my_minor = minor(buf.st_rdev);
- X sprintf(TtyName, "/dev/ttyq%d", my_minor);
- X if ((tf = open(TtyName, O_RDWR)) != -1)
- X {
- X close(tf);
- X#ifdef LOCKPTY
- X (void) ioctl(f, TIOCEXCL, (char *)0);
- X#endif
- X return f;
- X }
- X close(f);
- X }
- X }
- X }
- X return -1;
- X}
- X
- X# else /* SGI */
- X
- static int OpenPTY()
- X{
- X register f;
- X register my_minor;
- X struct stat buf;
- X
- X strcpy(PtyName, "/dev/ptc");
- X f = open(PtyName, O_RDWR|O_NDELAY);
- X if (f >= 0)
- X {
- X if (fstat(f, &buf) < 0)
- X {
- X close(f);
- X return -1;
- X }
- X my_minor = minor(buf.st_rdev);
- X sprintf(TtyName, "/dev/ttyq%d", my_minor);
- X }
- X return f;
- X}
- X
- X# endif /* SGI */
- X# else /* MIPS */
- X
- static int OpenPTY()
- X{
- X register char *p, *l, *d;
- X register int i, f, tf;
- X
- X strcpy(PtyName, PtyProto);
- X strcpy(TtyName, TtyProto);
- X for (p = PtyName, i = 0; *p != 'X'; ++p, ++i)
- X ;
- X#ifdef sequent
- X /* why ask for sequent in #else (not sequent) section? jw. */
- X for (l = "p"; (*p = *l) != '\0'; ++l)
- X { /* } */
- X for (d = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; (p[1] = *d) != '\0'; ++d)
- X { /* } */
- X#else
- X for (l = "qpr"; (*p = *l) != '\0'; ++l)
- X {
- X for (d = "0123456789abcdef"; (p[1] = *d) != '\0'; ++d)
- X {
- X#endif
- X if ((f = open(PtyName, O_RDWR)) != -1)
- X {
- X TtyName[i] = p[0];
- X TtyName[i + 1] = p[1];
- X if ((tf = open(TtyName, O_RDWR)) != -1)
- X {
- X /* close tf, thus we also get rid of an unwanted
- X * controlling terminal!
- X */
- X close(tf);
- X#ifdef LOCKPTY
- X (void) ioctl(f, TIOCEXCL, (char *) 0);
- X#endif
- X return f;
- X }
- X close(f);
- X }
- X }
- X }
- X return -1;
- X}
- X# endif /* MIPS */
- X#endif
- X
- void
- SetTTY(fd, mp)
- int fd;
- struct mode *mp;
- X{
- X errno = 0;
- X#ifdef POSIX
- X tcsetattr(fd, TCSADRAIN, &mp->tio);
- X# ifdef hpux
- X ioctl(fd, TIOCSLTC, &mp->m_ltchars);
- X# endif
- X#else
- X# ifdef TERMIO
- X ioctl(fd, TCSETA, &mp->tio);
- X# else
- X /* ioctl(fd, TIOCSETP, &mp->m_ttyb); */
- X ioctl(fd, TIOCSETC, &mp->m_tchars);
- X ioctl(fd, TIOCSLTC, &mp->m_ltchars);
- X ioctl(fd, TIOCLSET, &mp->m_lmode);
- X ioctl(fd, TIOCSETD, &mp->m_ldisc);
- X ioctl(fd, TIOCSETP, &mp->m_ttyb);
- X# endif
- X#endif
- X if (errno)
- X Msg(0, "SetTTY: ioctl", fd);
- X}
- X
- void
- GetTTY(fd, mp)
- int fd;
- struct mode *mp;
- X{
- X errno = 0;
- X#ifdef POSIX
- X tcgetattr(fd, &mp->tio);
- X# ifdef hpux
- X ioctl(fd, TIOCGLTC, &mp->m_ltchars);
- X# endif
- X#else
- X# ifdef TERMIO
- X ioctl(fd, TCGETA, &mp->tio);
- X# else
- X ioctl(fd, TIOCGETP, &mp->m_ttyb);
- X ioctl(fd, TIOCGETC, &mp->m_tchars);
- X ioctl(fd, TIOCGLTC, &mp->m_ltchars);
- X ioctl(fd, TIOCLGET, &mp->m_lmode);
- X ioctl(fd, TIOCGETD, &mp->m_ldisc);
- X# endif
- X#endif
- X if (errno)
- X Msg(0, "GetTTY: ioctl", fd);
- X}
- X
- void
- SetMode(op, np)
- struct mode *op, *np;
- X{
- X *np = *op;
- X
- X#if defined(TERMIO) || defined(POSIX)
- X np->tio.c_iflag &= ~ICRNL;
- X np->tio.c_oflag &= ~ONLCR;
- X np->tio.c_lflag &= ~(ICANON | ECHO);
- X np->tio.c_lflag |= ISIG;
- X/*
- X * careful, careful catche monkey..
- X * never set VMIN and VTIME to zero, if you want blocking io.
- X */
- X np->tio.c_cc[VMIN] = 1;
- X np->tio.c_cc[VTIME] = 0;
- X#ifdef VSTART
- X startc = op->tio.c_cc[VSTART];
- X#endif
- X#ifdef VSTOP
- X stopc = op->tio.c_cc[VSTOP];
- X#endif
- X if (iflag)
- X intrc = op->tio.c_cc[VINTR];
- X else
- X intrc = np->tio.c_cc[VINTR] = 0377;
- X np->tio.c_cc[VQUIT] = 0377;
- X if (flowctl == 1)
- X {
- X np->tio.c_cc[VINTR] = 0377;
- X#ifdef VSTART
- X np->tio.c_cc[VSTART] = 0377;
- X#endif
- X#ifdef VSTOP
- X np->tio.c_cc[VSTOP] = 0377;
- X#endif
- X#ifdef VDISCARD
- X np->tio.c_cc[VDISCARD] = 0377;
- X#endif
- X np->tio.c_iflag &= ~IXON;
- X }
- X#ifdef VSUSP
- X np->tio.c_cc[VSUSP] = 0377;
- X#endif
- X# ifdef hpux
- X np->m_ltchars.t_suspc = 0377;
- X np->m_ltchars.t_dsuspc = 0377;
- X np->m_ltchars.t_flushc = 0377;
- X np->m_ltchars.t_lnextc = 0377;
- X# else
- X# ifdef VDSUSP
- X np->tio.c_cc[VDSUSP] = 0377;
- X# endif
- X# endif
- X#else
- X startc = op->m_tchars.t_startc;
- X stopc = op->m_tchars.t_stopc;
- X if (iflag)
- X intrc = op->m_tchars.t_intrc;
- X else
- X intrc = np->m_tchars.t_intrc = -1;
- X np->m_ttyb.sg_flags &= ~(CRMOD | ECHO);
- X np->m_ttyb.sg_flags |= CBREAK;
- X np->m_tchars.t_quitc = -1;
- X if (flowctl == 1)
- X {
- X np->m_tchars.t_intrc = -1;
- X np->m_tchars.t_startc = -1;
- X np->m_tchars.t_stopc = -1;
- X }
- X np->m_ltchars.t_suspc = -1;
- X np->m_ltchars.t_dsuspc = -1;
- X np->m_ltchars.t_flushc = -1;
- X np->m_ltchars.t_lnextc = -1;
- X#endif /* defined(TERMIO) || defined(POSIX) */
- X}
- X
- void
- SetFlow(on)
- int on;
- X{
- X#if defined(TERMIO) || defined(POSIX)
- X if (on)
- X {
- X NewMode.tio.c_cc[VINTR] = intrc;
- X#ifdef VSTART
- X NewMode.tio.c_cc[VSTART] = startc;
- X#endif
- X#ifdef VSTOP
- X NewMode.tio.c_cc[VSTOP] = stopc;
- X#endif
- X NewMode.tio.c_iflag |= IXON;
- X }
- X else
- X {
- X NewMode.tio.c_cc[VINTR] = 0377;
- X#ifdef VSTART
- X NewMode.tio.c_cc[VSTART] = 0377;
- X#endif
- X#ifdef VSTOP
- X NewMode.tio.c_cc[VSTOP] = 0377;
- X#endif
- X NewMode.tio.c_iflag &= ~IXON;
- X }
- X# ifdef POSIX
- X if (tcsetattr(0, TCSADRAIN, &NewMode.tio))
- X# else
- X if (ioctl(0, TCSETA, &NewMode.tio) != 0)
- X# endif
- X debug1("SetFlow: ioctl errno %d\n", errno);
- X#else
- X if (on)
- X {
- X NewMode.m_tchars.t_intrc = intrc;
- X NewMode.m_tchars.t_startc = startc;
- X NewMode.m_tchars.t_stopc = stopc;
- X }
- X else
- X {
- X NewMode.m_tchars.t_intrc = -1;
- X NewMode.m_tchars.t_startc = -1;
- X NewMode.m_tchars.t_stopc = -1;
- X }
- X if (ioctl(0, TIOCSETC, &NewMode.m_tchars) != 0)
- X debug1("SetFlow: ioctl errno %d\n", errno);
- X#endif /* defined(TERMIO) || defined(POSIX) */
- X}
- X
- char *GetTtyName()
- X{
- X register char *p;
- X register int n;
- X
- X for (p = 0, n = 0; n <= 2 && ((p = ttyname(n)) == 0); n++)
- X ;
- X if (!p || *p == '\0')
- X Msg(0, "screen must run on a tty.");
- X return p;
- X}
- X
- X/* we return 1 if we could attach one, or 0 if none */
- static int Attach(how)
- int how;
- X{
- X int lasts;
- X struct msg m;
- X struct stat st;
- X char *tty, *s;
- X
- X if (how == MSG_WINCH)
- X {
- X bzero((char *) &m, sizeof(m));
- X m.type = how;
- X if ((lasts=MakeClientSocket(0,SockName))>=0)
- X {
- X write(lasts, &m, sizeof(m));
- X close(lasts);
- X }
- X return 0;
- X }
- X
- X switch (FindSocket(how, &lasts))
- X {
- X case 0:
- X if (rflag == 2)
- X return 0;
- X if (quietflag)
- X eexit(10);
- X Msg(0, "There is no screen to be %sed.", dflag ? "detach" : "resum");
- X /* NOTREACHED */
- X case 1:
- X break;
- X default:
- X Msg(0, "Type \"screen [-d] -r host.tty\" to resume one of them.");
- X /* NOTREACHED */
- X }
- X SockName = SockNamePtr;
- X debug1("Attach decided, it is '%s'\n", SockPath);
- X if (stat(SockPath, &st) == -1)
- X Msg(errno, "stat %s", SockPath);
- X if ((st.st_mode & 0700) != (dflag ? 0700 : 0600))
- X Msg(0, "That screen is %sdetached.", dflag ? "already " : "not ");
- X tty = GetTtyName();
- X if ((unsigned)strlen(tty) >= MAXPATH)
- X Msg(0, "TtyName too long - sorry.");
- X#ifdef REMOTE_DETACH
- X if (dflag &&
- X (how == MSG_ATTACH || how == MSG_DETACH || how == MSG_POW_DETACH))
- X {
- X strcpy(m.m.detach.tty, tty);
- X m.m.detach.dpid = getpid();
- X#ifdef POW_DETACH
- X if (dflag == 2)
- X m.type = MSG_POW_DETACH;
- X else
- X#endif
- X m.type = MSG_DETACH;
- X trysend(lasts, &m, m.m.detach.password);
- X if (how != MSG_ATTACH)
- X return 0; /* we detached it. jw. */
- X sleep(1); /* we dont want to overrun our poor backend. jw. */
- X if ((lasts = MakeClientSocket(0, SockName)) == -1)
- X Msg(0, "Cannot contact screen again. Shit.");
- X }
- X#endif
- X m.type = how;
- X strcpy(m.m.attach.tty, tty);
- X s = getenv("TERM");
- X if (s)
- X {
- X if ((unsigned)strlen(s) >= MAXPATH-5)
- X Msg(0, "$TERM too long - sorry.");
- X sprintf(m.m.attach.envterm, "TERM=%s", s);
- X }
- X else
- X *m.m.attach.envterm = '\0';
- X debug1("attach: sending %d bytes... ", sizeof m);
- X
- X m.m.attach.apid = getpid();
- X m.m.attach.adaptflag = adaptflag;
- X m.m.attach.lines = m.m.attach.columns = 0;
- X if (s = getenv("LINES"))
- X m.m.attach.lines = atoi(s);
- X if (s = getenv("COLUMNS"))
- X m.m.attach.columns = atoi(s);
- X
- X trysend(lasts, &m, m.m.attach.password);
- X debug1("Attach(%d): sent\n", m.type);
- X Suspended = 0;
- X rflag = 0;
- X return 1;
- X}
- X
- X
- X#ifdef PASSWORD
- X
- static trysendstat;
- X
- static sig_t trysendok(SIGDEFARG)
- X{
- X trysendstat = 1;
- X}
- X
- static sig_t trysendfail(SIGDEFARG)
- X{
- X trysendstat = -1;
- X}
- X
- static char screenpw[9];
- X
- static void trysend(fd, m, pwto)
- int fd;
- struct msg *m;
- char *pwto;
- X{
- X char *npw = NULL;
- X sig_t (*sighup)();
- X sig_t (*sigusr1)();
- X
- X sigusr1 = signal(SIG_PW_OK, trysendok);
- X sighup = signal(SIG_PW_FAIL, trysendfail);
- X for (;;)
- X {
- X strcpy(pwto, screenpw);
- X trysendstat = 0;
- X if (write(fd, (char *) m, sizeof(*m)) != sizeof(*m))
- X Msg(errno, "write");
- X close(fd);
- X while (trysendstat == 0)
- X pause();
- X if (trysendstat > 0)
- X {
- X signal(SIG_PW_OK, sigusr1);
- X signal(SIG_PW_FAIL, sighup);
- X return;
- X }
- X if (*screenpw || (npw = getpass("Screen Password:")) == 0 || *npw == 0)
- X Msg(0, "Password incorrect");
- X strncpy(screenpw,npw,8);
- X if ((fd = MakeClientSocket(0, SockName)) == -1)
- X Msg(0, "Cannot contact screen again. Shit.");
- X#ifdef SYSV
- X signal(SIG_PW_FAIL, trysendfail);
- X#endif
- X }
- X}
- X
- X#else /* PASSWORD */
- X
- static trysend(fd, m, pwto)
- struct msg *m;
- char *pwto;
- X{
- X strcpy(pwto, "");
- X if (write(fd, (char *) m, sizeof(*m)) != sizeof(*m))
- X Msg(errno, "write");
- X close(fd);
- X}
- X
- X#endif /* PASSWORD */
- X
- X
- X/*
- X * Unfortunatelly this is also the SIGHUP handler, so we have to
- X * check, if the backend is already detached.
- X */
- X
- static sig_t AttacherFinit(SIGDEFARG)
- X{
- X struct stat statb;
- X struct msg m;
- X int s;
- X
- X debug("AttacherFinit();\n");
- X /* Check if signal comes from backend */
- X if (SockName)
- X {
- X strcpy(SockNamePtr, SockName);
- X if (stat(SockPath, &statb) == 0 && (statb.st_mode & 0777) != 0600)
- X {
- X debug("Detaching backend!\n");
- X bzero((char *) &m, sizeof(m));
- X strcpy(m.m.detach.tty, GetTtyName());
- X m.m.detach.dpid = getpid();
- X#ifdef PASSWORD
- X strcpy(m.m.detach.password, screenpw);
- X signal(SIG_PW_OK, SIG_IGN);
- X signal(SIG_PW_FAIL, SIG_IGN);
- X#endif
- X m.type = MSG_HANGUP;
- X if ((s=MakeClientSocket(0, SockName))>=0)
- X {
- X write(s, &m, sizeof(m));
- X close(s);
- X }
- X }
- X }
- X exit(0);
- X#ifndef SIGVOID
- X return((sig_t) 0);
- X#endif
- X}
- X
- X#ifdef POW_DETACH
- static sig_t AttacherFinitBye(SIGDEFARG)
- X{
- X int ppid;
- X debug("AttacherFintBye()\n");
- X freetty();
- X setuid(real_uid);
- X setgid(real_gid);
- X /* we don't want to disturb init (even if we were root), eh? jw */
- X if ((ppid = getppid()) > 1)
- X Kill(ppid, SIGHUP); /* carefully say good bye. jw. */
- X exit(0);
- X#ifndef SIGVOID
- X return((sig_t) 0);
- X#endif
- X}
- X#endif
- X
- static SuspendPlease;
- X
- static sig_t SigStop(SIGDEFARG)
- X{
- X debug("SigStop()\n");
- X SuspendPlease = 1;
- X#ifndef SIGVOID
- X return((sig_t) 0);
- X#endif
- X}
- X
- X#ifdef LOCK
- static LockPlease;
- X
- static sig_t DoLock(SIGDEFARG)
- X{
- X debug("DoLock()\n");
- X LockPlease = 1;
- X# ifdef SYSV
- X signal(SIG_LOCK, DoLock);
- X# endif
- X# ifndef SIGVOID
- X return((sig_t) 0);
- X# endif
- X}
- X#endif
- X
- X#if defined(SIGWINCH) && defined(TIOCGWINSZ)
- static SigWinchPlease;
- X
- static sig_t SigAttWinch(SIGDEFARG)
- X{
- X debug("SigAttWinch()\n");
- X SigWinchPlease = 1;
- X# ifndef SIGVOID
- X return((sig_t) 0);
- X# endif
- X}
- X#endif
- X
- static void Attacher()
- X{
- X /*
- X * permanent in UserContext. Advantage is, you can kill your attacher
- X * when things go wrong. Any disadvantages? jw.
- X */
- X setuid(real_uid);
- X setgid(real_gid);
- X
- X signal(SIGHUP, AttacherFinit);
- X signal(SIG_BYE, AttacherFinit);
- X#ifdef POW_DETACH
- X signal(SIG_POWER_BYE, AttacherFinitBye);
- X#endif
- X#ifdef LOCK
- X signal(SIG_LOCK, DoLock);
- X#endif
- X signal(SIGINT, SIG_IGN);
- X#ifdef BSDJOBS
- X signal(SIG_STOP, SigStop);
- X#endif
- X#if defined(SIGWINCH) && defined(TIOCGWINSZ)
- X signal(SIGWINCH, SigAttWinch);
- X#endif
- X#ifdef DEBUG
- X# ifdef SYSV
- X signal(SIGCLD,FEChld);
- X# else
- X signal(SIGCHLD,FEChld);
- X# endif
- X#endif
- X debug("attacher: going for a nap.\n");
- X dflag = 0;
- X while (1)
- X {
- X pause();
- X debug("attacher: huh! a signal!\n");
- X#ifdef DEBUG
- X if (FEpanic)
- X {
- X printf("\n\rSuddenly the Dungeon collapses!! - You die...\n\r");
- X SetTTY(0, &OldMode);
- X eexit(1);
- X }
- X#endif
- X#ifdef BSDJOBS
- X if (SuspendPlease)
- X {
- X SuspendPlease = 0;
- X signal(SIGTSTP, SIG_DFL);
- X debug("attacher: killing myself SIGTSTP\n");
- X kill(getpid(), SIGTSTP);
- X
- X debug1("attacher: continuing from stop(%d)\n", Suspended);
- X signal(SIG_STOP, SigStop);
- X (void) Attach(MSG_CONT);
- X }
- X#endif
- X#ifdef LOCK
- X if (LockPlease)
- X {
- X LockPlease = 0;
- X LockTerminal();
- X# ifdef SYSV
- X signal(SIG_LOCK, DoLock);
- X# endif
- X (void) Attach(MSG_CONT);
- X }
- X#endif /* LOCK */
- X#if defined(SIGWINCH) && defined(TIOCGWINSZ)
- X if (SigWinchPlease)
- X {
- X SigWinchPlease = 0;
- X# ifdef SYSV
- X signal(SIGWINCH, SigAttWinch);
- X# endif
- X (void) Attach(MSG_WINCH);
- X }
- X#endif /* SIGWINCH */
- X }
- X}
- X
- X#ifdef LOCK
- X
- X/* ADDED by Rainer Pruy 10/15/87 */
- X/* POLISHED by mls. 03/10/91 */
- X
- static char LockEnd[] = "Welcome back to screen !!\n";
- X
- static void LockTerminal()
- X{
- X char *prg;
- X int sig, pid;
- X sig_t (*sigs[NSIG])__P(SIGPROTOARG);
- X
- X for (sig = 1; sig < NSIG; sig++)
- X {
- X sigs[sig] = signal(sig, SIG_IGN);
- X }
- X SetTTY(0, &OldMode);
- X printf("\n");
- X
- X prg = getenv("LOCKPRG");
- X if (prg && strcmp(prg,"builtin") && !access(prg, X_OK))
- X {
- X debug1("lockterminal: '%s' seems executable, execl it!\n", prg);
- X if ((pid = fork()) == 0)
- X {
- X /* Child */
- X setuid(real_uid); /* this should be done already */
- X setgid(real_gid);
- X execl(prg, "SCREEN-LOCK", NULL);
- X exit(errno);
- X }
- X if (pid == -1)
- X {
- X#ifdef NETHACK
- X if (nethackflag)
- X Msg(errno, "Cannot fork terminal - lock failed");
- X else
- X#endif
- X Msg(errno, "Cannot lock terminal - fork failed");
- X }
- X else
- X {
- X#ifdef BSDWAIT
- X union wait wstat;
- X#else
- X int wstat;
- X#endif
- X int wret;
- X
- X#ifdef hpux
- X signal(SIGCLD, SIG_DFL);
- X#endif
- X errno = 0;
- X while (((wret = wait((int *) &wstat)) != pid) ||
- X ((wret == -1) && (errno == EINTR))
- X )
- X errno = 0;
- X
- X if (errno)
- X {
- X perror("Lock");
- X sleep(2);
- X }
- X else if (WTERMSIG(wstat) != 0)
- X {
- X fprintf(stderr, "Lock: %s: Killed by signal: %d%s\n", prg,
- X WTERMSIG(wstat), WIFCORESIG(wstat) ? " (Core dumped)" : "");
- X sleep(2);
- X }
- X else if (WEXITSTATUS(wstat))
- X {
- X debug2("Lock: %s: return code %d\n", prg, WEXITSTATUS(wstat));
- X }
- X else
- X printf(LockEnd);
- X }
- X }
- X else
- X {
- X if (prg)
- X {
- X debug1("lockterminal: '%s' seems NOT executable, we use our builtin\n", prg);
- X }
- X else
- X {
- X debug("lockterminal: using buitin.\n");
- X }
- X screen_builtin_lck();
- X }
- X /* reset signals */
- X for (sig = 1; sig < NSIG; sig++)
- X {
- X if (sigs[sig] != (sig_t(*) ()) - 1)
- X signal(sig, sigs[sig]);
- X }
- X} /* LockTerminal */
- X
- X/* -- original copyright by Luigi Cannelloni 1985 (luigi@faui70.UUCP) -- */
- void
- screen_builtin_lck()
- X{
- X char fullname[100],*cp1, message[BUFSIZ];
- X char c,*pass,mypass[9];
- X int t;
- X
- X#ifdef undef
- X /* get password entry */
- X if ((ppp = getpwuid(real_uid)) == NULL)
- X {
- X fprintf(stderr,"screen_builtin_lck: No passwd entry.\007\n");
- X sleep(2);
- X return;
- X }
- X if (!isatty(0))
- X {
- X fprintf(stderr,"screen_builtin_lck: Not a tty.\007\n");
- X sleep(2);
- X return;
- X }
- X#endif
- X for (t=0; t<13; t++)
- X {
- X c=ppp->pw_passwd[t];
- X if (!(c == '.' || c == '/' ||
- X c>='0' && c<='9' ||
- X c>='a' && c<='z' ||
- X c>='A' && c<='Z')) break;
- X }
- X if (t<13)
- X {
- X debug("builtin_lock: ppp->pw_passwd bad, has it a shadow?\n");
- X if (pass=getpass("Key: "))
- X {
- X strncpy(mypass,pass,8);
- X mypass[8]=0;
- X if (*mypass==0)
- X return;
- X if (pass=getpass("Again: "))
- X {
- X if (strcmp(mypass,pass))
- X {
- X fprintf(stderr,"Passwords don't match.\007\n");
- X sleep(2);
- X return;
- X }
- X }
- X }
- X if (pass==0)
- X {
- X fprintf(stderr,"Getpass error.\007\n");
- X sleep(2);
- X return;
- X }
- X pass=0;
- X }
- X else pass=ppp->pw_passwd;
- X
- X debug("screen_builtin_lck looking in gcos field\n");
- X strcpy(fullname,ppp->pw_gecos);
- X if ((cp1 = index(fullname,',')) != NULL)
- X *cp1 = '\0';
- X if ((cp1 = index(fullname,'&')) != NULL)
- X {
- X sprintf(cp1,"%s",ppp->pw_name);
- X *cp1 = islower(*cp1) ? toupper(*cp1) : *cp1;
- X }
- X
- X sprintf(message,"Screen used by %s <%s>.\nPassword:\007",
- X fullname, ppp->pw_name);
- X
- X /* loop here to wait for correct password */
- X for (;;)
- X {
- X debug("screen_builtin_lck awaiting password\n");
- X if (pass)
- X {
- X if(!strcmp(crypt(getpass(message),pass),pass))
- X break;
- X }
- X else
- X {
- X if(!strcmp(getpass(message),mypass))
- X break;
- X }
- X debug("screen_builtin_lck: NO!!!!!\n");
- X }
- X debug("password ok.\n");
- X}
- X
- X#endif /* LOCK */
- X
- X/*
- X * Detach now has the following modes:
- X * D_DETACH SIG_BYE detach backend and exit attacher
- X * D_STOP SIG_STOP stop attacher (and detach backend)
- X * D_REMOTE SIG_BYE remote detach -- reattach to new attacher
- X * D_POWER SIG_POWER_BYE power detach -- attacher kills his parent
- X * D_REMOTE_POWER SIG_POWER_BYE remote power detach -- both
- X * D_LOCK SIG_LOCK lock the attacher
- X * (jw)
- X * we always remove our utmp slots. (even when "lock" or "stop")
- X * Note: Take extra care here, we may be called by unterrupt!
- X */
- void
- Detach(mode)
- int mode;
- X{
- X int sign = 0;
- X#ifdef UTMPOK
- X register int n;
- X#endif
- X
- X if (Detached)
- X return;
- X debug1("Detach(%d)\n", mode);
- X if (fore && status)
- X RemoveStatus();
- X signal(SIGHUP, SIG_IGN);
- X SetTTY(0, &OldMode);
- X FinitTerm();
- X switch (mode)
- X {
- X case D_DETACH:
- X printf("\n[detached]\n");
- X sign = SIG_BYE;
- X break;
- X#ifdef BSDJOBS
- X case D_STOP:
- X (void) fflush(stdout);
- X sign = SIG_STOP;
- X break;
- X#endif
- X#ifdef REMOTE_DETACH
- X case D_REMOTE:
- X printf("\n[remote detached]\n");
- X sign = SIG_BYE;
- X break;
- X#endif
- X#ifdef POW_DETACH
- X case D_POWER:
- X printf("\n[power detached]\n");
- X if (PowDetachString)
- X printf("%s\n",PowDetachString);
- X sign = SIG_POWER_BYE;
- X break;
- X#ifdef REMOTE_DETACH
- X case D_REMOTE_POWER:
- X printf("\n[remote power detached]\n");
- X if (PowDetachString)
- X printf("%s\n",PowDetachString);
- X sign = SIG_POWER_BYE;
- X break;
- X#endif
- X#endif
- X case D_LOCK:
- X ClearDisplay();
- X sign = SIG_LOCK;
- X /* tell attacher to lock terminal with a lockprg. */
- X break;
- X }
- X#ifdef UTMPOK
- X for (n = WinList; n != -1; n = wtab[n]->WinLink)
- X if (wtab[n]->slot != (slot_t) -1)
- X {
- X RemoveUtmp(wtab[n]);
- X /*
- X * Set the slot to 0 to get the window
- X * logged in again.
- X */
- X wtab[n]->slot = (slot_t) 0;
- X }
- X RestoreLoginSlot();
- X#endif
- X freetty();
- X debug("Detach: we did freetty().\n");
- X (void) chmod(SockPath, /* S_IFSOCK | */ 0600); /* Flag detached-ness */
- X /*
- X * tell father to father what to do. We do that after we
- X * freed the tty, thus getty feels more comfortable on hpux
- X * if it was a power detach.
- X */
- X Kill(AttacherPid,sign);
- X debug2("Detach: Signal %d to Attacher(%d)!\n", sign, AttacherPid);
- X if (mode != D_LOCK && mode != D_STOP)
- X AttacherPid = 0;
- X
- X Detached = 1;
- X Suspended = (mode == D_STOP) ? 1 : 0;
- X if (fore)
- X fore->active = 0;
- X debug("Detach returns, we are successfully detached.\n");
- X}
- X
- int
- CheckPid(pid)
- int pid;
- X{
- X if (pid < 2)
- X return(-1);
- X if (eff_uid == real_uid)
- X return kill(pid, 0);
- X if (UserContext() == 1)
- X {
- X UserReturn(kill(pid, 0));
- X }
- X return UserStatus();
- X}
- X
- void
- Kill(pid, sig)
- int pid, sig;
- X{
- X if (pid < 2)
- X return;
- X (void) kill(pid, sig);
- X}
- X
- static int IsSymbol(e, s)
- register char *e, *s;
- X{
- X register char *p;
- X register int n;
- X
- X for (p = e; *p && *p != '='; ++p)
- X ;
- X if (*p)
- X {
- X *p = '\0';
- X n = strcmp(e, s);
- X *p = '=';
- X return n == 0;
- X }
- X return 0;
- X}
- X
- static void MakeNewEnv()
- X{
- X register char **op, **np;
- X static char buf[MAXSTR];
- X
- X for (op = environ; *op; ++op)
- X ;
- X NewEnv = np = (char **) malloc((unsigned) (op - environ + 6 + 1) * sizeof(char **));
- X if (!NewEnv)
- X Msg_nomem;
- X if ((unsigned)strlen(SockName) > MAXSTR - 5)
- X SockName = "?";
- X sprintf(buf, "STY=%s", SockName);
- X *np++ = buf; /* NewEnv[0] */
- X *np++ = Term; /* NewEnv[1] */
- X#ifdef TIOCGWINSZ
- X np += 2; /* leave room for TERMCAP and WINDOW */
- X#else
- X np += 4; /* room for TERMCAP WINDOW LINES COLUMNS */
- X#endif
- X
- X for (op = environ; *op; ++op)
- X {
- X if (!IsSymbol(*op, "TERM") && !IsSymbol(*op, "TERMCAP")
- X && !IsSymbol(*op, "STY") && !IsSymbol(*op, "WINDOW")
- X && !IsSymbol(*op, "SCREENCAP")
- X#ifndef TIOCGWINSZ
- X && !IsSymbol(*op, "LINES") && !IsSymbol(*op, "COLUMNS")
- X#endif
- X )
- X *np++ = *op;
- X }
- X *np = 0;
- X}
- X
- void
- X#ifdef USEVARARGS
- X/*VARARGS2*/
- X# if defined(__STDC__)
- Msg(int err, char *fmt, ...)
- X# else
- Msg(err, fmt, va_alist)
- int err;
- char *fmt;
- va_dcl
- X# endif
- X{
- X static va_list ap = 0;
- X#else
- X/*VARARGS2*/
- Msg(err, fmt, p1, p2, p3, p4, p5, p6)
- int err;
- char *fmt;
- unsigned long p1, p2, p3, p4, p5, p6;
- X{
- X#endif
- X char buf[MAXPATH*2];
- X char *p = buf;
- X
- X if (Detached)
- X return;
- X#ifdef USEVARARGS
- X# if defined(__STDC__)
- X va_start(ap, fmt);
- X# else
- X va_start(ap);
- X# endif
- X (void) vsprintf(p, fmt, ap);
- X va_end(ap);
- X#else
- X sprintf(p, fmt, p1, p2, p3, p4, p5, p6);
- X#endif
- X if (err)
- X {
- X p += strlen(p);
- X if (err > 0 && err < sys_nerr)
- X sprintf(p, ": %s", sys_errlist[err]);
- X else
- X sprintf(p, ": Error %d", err);
- X }
- X if (HasWindow)
- X {
- X debug1("Msg('%s');\n", p);
- X MakeStatus(buf);
- X }
- X else
- X {
- X printf("%s\r\n", buf);
- X if (DeadlyMsg)
- X {
- X debug1("Msg('%s') screen is not up, exiting..\n", buf);
- X Kill(AttacherPid, SIG_BYE);
- X eexit(1);
- X }
- X else
- X debug1("Harmless = 0; Msg('%s');\n", buf);
- X }
- X DeadlyMsg = 1;
- X}
- X
- char *Filename(s)
- char *s;
- X{
- X register char *p;
- X
- X if (s == NULL)
- X return s;
- X p = s + strlen(s) - 1;
- X while (p >= s && *p != '/')
- X --p;
- X return ++p;
- X}
- X
- X/*
- X * '^' is allowed as an escape mechanism for control characters. jw.
- X */
- static char *MakeWinMsg(s, n)
- register char *s;
- int n;
- X{
- X static char buf[MAXSTR];
- X register char *p = buf;
- X register int ctrl;
- X
- X ctrl = 0;
- X for (; *s && p < buf + MAXSTR - 1; s++, p++)
- X if (ctrl)
- X {
- X ctrl = 0;
- X if (*s == '^' || *s < 64)
- X *p = *s;
- X else
- X *p = *s - 64;
- X }
- X else
- X {
- X switch (*s)
- X {
- X case '%':
- X *p = n + '0';
- X break;
- X case '~':
- X *p = BELL;
- X break;
- X case '^':
- X ctrl = 1;
- X *p-- = '^';
- X break;
- X default:
- X *p = *s;
- X break;
- X }
- X }
- X *p = '\0';
- X return buf;
- X}
- X
- END_OF_FILE
- if test 78493 -ne `wc -c <'screen.c'`; then
- echo shar: \"'screen.c'\" unpacked with wrong size!
- fi
- # end of 'screen.c'
- fi
- echo shar: End of archive 8 \(of 8\).
- cp /dev/null ark8isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 8 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-